はじめに
ZOOM勉強会の議事録です。 「増補改訂版Java言語で学ぶデザインパターン入門」を読んで、プログラム作成・パターンの理解を行います。 第9回はBridgeパターンです。Bridge
Bridgeパターンは、実装と機能を2つのクラスに分離するパターンです。ブリッジパターンの役割は以下です。
- Implementor 実装のクラス階層の最上位クラス
- ConcreteImplementor 具体的な実装を行うクラス
- Abstraction 機能の階層の最上位クラス
- RefinedAbstraction 実際に機能を追加したもの
実装と機能
まず実装と機能について説明します。実装
抽象クラス・インタフェースで定義した抽象メソッドを実装することを指します。 以下のように階層としては、横に伸びていきます。 AbstractClass -ConcreteCrass -AnotherConcreteClass機能
あるクラスに新しいメソッドを追加するため、継承を行うことを指します。 階層としては、深さ方向に伸びていきます。 Something -SomethingGood -SomethingBetterImplementor
実装のクラス階層の最上位のクラスとなります。DisplayImpl
Public MustInherit Class DisplayImpl
Public MustOverride Sub RawOpen()
Public MustOverride Sub RawPrint()
Public MustOverride Sub RawClose()
End Class
ConcreteImplementor
具体的な実装を行うクラスです。 今回は`DisplayImpl`インタフェースのメソッドを実装して、装飾した文字列を表示します。StringDisplayImpl
'以下のような形で文字列を表示
'+------+
'|string|
'+------+
Public Class StringDisplayImpl : Inherits DisplayImpl
''' 文字の長さ
Private width As Integer
''' 表示する文字列
Private str As String
''' コンストラクタ
Public Sub New(ByVal str As String)
Me.str = str
Me.width = str.Length
End Sub
''' 開く
Public Overrides Sub RawOpen()
PrintLine()
End Sub
''' 書く
Public Overrides Sub RawPrint()
Console.WriteLine("|" & str & "|")
End Sub
''' 閉じる
Public Overrides Sub RawClose()
PrintLine()
End Sub
''' (1)開く(2)閉じる の実装
Private Sub PrintLine()
Console.Write("+")
For i As Integer = 0 To width - 1
Console.Write("-")
Next
Console.WriteLine("+")
End Sub
End Class
実装の階層としてもう一つ、wで文字を囲むものを作成します。
WWDisplay
'以下のような形で文字列を表示
'WwwwwwwwwwwwwW
'Www string wwW
'WwwwwwwwwwwwwW
Public Class WWDisplay : Inherits DisplayImpl
Private width As Integer
Private str As String
Public Sub New(ByVal str As String)
Me.str = str
Me.width = str.Length
End Sub
Public Overrides Sub RawOpen()
PrintLine()
End Sub
Public Overrides Sub RawPrint()
Console.WriteLine("Www " & str & " wwW")
End Sub
Public Overrides Sub RawClose()
PrintLine()
End Sub
Private Sub PrintLine()
Console.Write("W")
For i As Integer = 0 To width + 5
Console.Write("w")
Next
Console.WriteLine("W")
End Sub
End Class
Abstraction
機能のクラス階層の最上位のクラスになります。Display
Public Class Display
''' 抽象クラス
Private _impl As DisplayImpl
''' コンストラクタ:抽象クラスでもらう
Public Sub New(ByVal impl As DisplayImpl)
Me._impl = impl
End Sub
''' 開く
Public Sub Open()
_impl.RawOpen()
End Sub
''' 書く
Public Sub Print()
_impl.RawPrint()
End Sub
''' 閉じる
Public Sub Close()
_impl.RawClose()
End Sub
End Class
RefinedAbstraction
`Display`クラスに機能を追加したものになります。 今回は指定された回数表示するという機能を追加しています。RefinedAbstraction
Public Class CountDisplay : Inherits Display
''' コンストラクタ:抽象クラスでもらう
Public Sub New(ByVal impl As DisplayImpl)
'基底クラスのコンストラクタ
MyBase.New(impl)
End Sub
''' 指定された回数だけ、"書く"を繰り返す
Public Sub MultiDisplay(ByVal times As Short)
'開く
Me.Open()
'指定された回数だけ"書く"を繰り返す
For i As Integer = 0 To times
Print()
Next
'閉じる
Me.Close()
End Sub
End Class
アンチパターン
実装と機能を2つのクラスに分離しなかった場合、指定された回数文字列を表示する機能をConcreteImplementor役の派生で実現することになります。 すると、`StringDisplayImpl`クラスと`WWDisplayImpl`クラス、両方にその機能が欲しい場合には、それぞれのクラスを派生して、それぞれで機能を追加しなければなりません。 この場合、ConcreteImplementor役の数だけクラスを増やす必要があります。 一方で、Bridgeパターンを使用した場合は、RefinedAbstraction役を1つ追加してやればよいだけとなります。anti
Public Class StringDisplayCount : Inherits StringDisplayImpl
Public Sub New(ByVal str As String)
MyBase.New(str)
End Sub
''' 指定された回数だけ、"書く"を繰り返す
Public Sub MultiDisplay(ByVal times As Short)
'開く
Me.RawOpen()
'指定された回数だけ"書く"を繰り返す
For i As Integer = 0 To times
RawPrint()
Next
'閉じる
Me.RawClose()
End Sub
End Class