LoginSignup
0
0

More than 1 year has passed since last update.

デザインパターン勉強会⑨Bridge

Posted at

はじめに

ZOOM勉強会の議事録です。
「増補改訂版Java言語で学ぶデザインパターン入門」を読んで、プログラム作成・パターンの理解を行います。
第9回はBridgeパターンです。

Bridge

Bridgeパターンは、実装と機能を2つのクラスに分離するパターンです。

ブリッジパターンの役割は以下です。

  • Implementor
  • 実装のクラス階層の最上位クラス
  • ConcreteImplementor
  • 具体的な実装を行うクラス
  • Abstraction
  • 機能の階層の最上位クラス
  • RefinedAbstraction
  • 実際に機能を追加したもの

実装と機能

まず実装と機能について説明します。

実装

抽象クラス・インタフェースで定義した抽象メソッドを実装することを指します。
以下のように階層としては、横に伸びていきます。
AbstractClass
 -ConcreteCrass
 -AnotherConcreteClass

機能

あるクラスに新しいメソッドを追加するため、継承を行うことを指します。
階層としては、深さ方向に伸びていきます。
Something
 -SomethingGood
  -SomethingBetter

Implementor

実装のクラス階層の最上位のクラスとなります。

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

まとめ

今回はBridgeパターンを学びました。
これも「継承より委譲」の一種なのかなと思いました。
機能と実装を意識することが殆どなかったので、今後はちゃんと意識して設計・コーディングを行っていきたいです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0