Bridgeパターン
機能と実装を分離して、それぞれを独立に拡張する

Bridgeパターンとは、「Bridge」すなわち「橋」の役割を果たすパターンです。Bridgeパターンを利用することで、クラスの機能と実装を分離して、それぞれを独立に拡張することができるようになります。
例えば、文字列をすべて大文字や小文字で表示する2つのクラスがあります。また、文字列をそのまま [ ] で囲んで表示するクラスもあります。このとき、[ ] で囲んで大文字や小文字で表示できるようにしようと思ったら、[ ] で囲んで表示するクラスを継承した、大文字で表示するクラスと小文字で表示するクラスを追加する必要があります。
今回のように、大文字や小文字の2つのクラスだけなら手間はそんなにかかりませんが、場合によっては、何十というクラスを作成することが必要となります。Bridge パターンは、機能を拡張するための階層と実装を拡張するための階層を分離することにより、このようなわずらわしさを解消し、拡張を容易にするものです。
「継承」はクラスを拡張するために便利な方法ですが、クラス間の結びつきをがっちり固定してしまいます。ソースコード上に継承元となるクラスを記述して、そのクラスのサブクラスであると定義するからです。そして、この関係はソースコードを書き換えない限り変えることはできません。実行時に必要に応じてクラス間の関係を切り替えたいときには、継承を使うのは不適切です。したがって、このようなときには、「継承」ではなく「委譲」を使います。
「委譲」 とは、実行時に引き渡されたインスタンスを保持し、そのメソッドを呼び出すことです。つまり、 「仕事をしろ」といわれたら、そのインスタンスのメソッドに丸投げするわけです。
Bridgeパターンを使用すると、基本的な機能を実装するインタフェース(例えばAPI)と、アプリケーション側から利用しやすいインタフェース(例えば処理メニュー)を提供するクラスとを別々に用意し、これらをBridgeとして結合するようクラスライブラリを設計することにより、効率よく複数のプラットフォームに対応することができるはずです。もちろん、異なるOSで動作するアプリケーションを提供する場合にも使えるでしょう。
こういったアプリケーションにとって、基本となるクラスライブラリを提供するという機会は、ある程度経験を積んでからでないとないかもしれません。しかし、普段からこういった設計もできるようになっていないと、いざ実際の仕事で使用したいといった場合に余裕を持って対応することができないでしょう。そういった意味でこのパターンは、少々ハードルが高いかもしれませんが、知っておく価値のあるパターンです。
例題
文字列をすべて大文字にして出力するクラスとすべて小文字にして出力するクラスを作りなさい。
さらに、それらの前後を [ ] で囲むクラスも作りなさい。
abcdefgh
ABCDEFGH
[ABCDEFGH]
共通クラス
|
Bridgeパターンを使用しない例 AbstractDisplayOrnament.java public abstract class AbstractDisplayOrnament implements IDisplay {
public void displayOrnament(String str) {
System.out.print("[");
display(str);
System.out.print("]");
}
}
DisplayOrnamentLowercase.java public class DisplayOrnamentLowercase extends AbstractDisplayOrnament {
public void display(String str) {
System.out.print(str.toLowerCase());
}
}
DisplayOrnamentUppercase.java public class DisplayOrnamentUppercase extends AbstractDisplayOrnament {
public void display(String str) {
System.out.print(str.toUpperCase());
}
}
Main.java public class Main {
public static void main(String[] args) {
IDisplay dispU = new DisplayUppercase();
dispU.display("AbCdEfGh"); System.out.println();
IDisplay dispL = new DisplayLowercase();
dispL.display("AbCdEfGh"); System.out.println();
AbstractDisplayOrnament dispOU = new DisplayOrnamentUppercase();
dispOU.display("AbCdEfGh"); System.out.println();
dispOU.displayOrnament("AbCdEfGh"); System.out.println();
}
}
|
Bridgeパターンを使用した例 DisplayNormal.java public class DisplayNormal {
private IDisplay displayImplement;
public DisplayNormal(IDisplay dispImp) {
this.displayImplement = dispImp;
}
public void display(String str) {
displayImplement.display(str);
}
}
DisplayOrnament.java public class DisplayOrnament extends DisplayNormal {
public DisplayOrnament(IDisplay dispImp) {
super(dispImp);
}
public void displayOrnament(String str) {
System.out.print("[");
display(str);
System.out.print("]");
}
}
Main.java public class Main {
public static void main(String[] args) {
DisplayNormal dispU = new DisplayNormal(new DisplayUppercase());
dispU.display("AbCdEfGh"); System.out.println();
DisplayNormal dispL = new DisplayNormal(new DisplayLowercase());
dispL.display("AbCdEfGh"); System.out.println();
DisplayOrnament dispOU = new DisplayOrnament(new DisplayUppercase());
dispOU.display("AbCdEfGh"); System.out.println();
dispOU.displayOrnament("AbCdEfGh"); System.out.println();
}
}
|
|
大文字で表示する DisplayUppercase、小文字で表示する DisplayLowercase があるにもかかわらず、[] で囲む DisplayOrnamentUppercase や DisplayOrnamentLowercase の中にも大文字や小文字にする機能を作らなければなりません。 よって、(大文字小文字の2種類)×(修飾有り無しの2種類)分のクラスが必要になります。 |
Bridge パターンでは、実装の変更が考えられるメソッドに関しては、実装用のクラス階層に委譲するように設計します。実装用のクラス階層とは、ここでは display メソッドの実装を与えるクラス階層として、IDisplay インタフェースをインプリメントするクラス階層を考えます。具体的には、Display クラス、 IDisplay インタフェースをコーディング例のようにしておきます。 Display クラスは、コンストラクタで、引数とした渡された、大文字や小文字で表示するクラスのインスタンスをdisplayImplement に保存し、display メソッドで、そのインスタンスのdisplayメソッドを呼び出します。そして、[ ] で囲むクラスのスーパークラスとなります。 IDisplay は、大文字や小文字で表示するクラスに共通するインタフェースとなります。 そして、実際に大文字や小文字に変換する機能を実装する DisplayUppercase クラスと DisplayLowercase クラスを IDisplay インタフェースをインプリメントしたクラスとして作成するようにします。 このような設計にしておくと、機能を追加するために、 Display クラスを継承して作成した新しいクラスでも、すでに存在する実装部分を利用することができるようになります。例えば、 Display クラスを継承して、[]で囲んで表示できるようにした DisplayOrnament クラスです。すでに存在している、大文字や小文字で表示する機能を利用できるのです。 例えば、DisplayUppercase のインスタンスを引数に DisplayOrnament のインスタンスを生成します(displayImplement に DisplayUppercase のインスタンスが保存されます)。そして、そのインスタンスの displayOrnament メソッドを呼び出せば、“[” の表示に続いて、(DisplayOrnament のスーパークラスである Display の display メソッドが呼び出され、displayImplement に保存されているインスタンス、すなわち)DisplayUppercase のdisplay メソッドが呼び出され、文字列が大文字で表示されます。そして、“]” の表示がされます。 このように、機能を拡張するためのクラス階層と、実装を拡張するためのクラス階層を分けておくことで、実装階層クラスと機能拡張クラスを好みの組み合わせで利用することができるようになります。今回の例では、 IDisplay インタフェースと Display クラスが機能拡張クラス階層と実装拡張クラス階層を橋渡しする役目を果たしています。 |
共通クラス
|
Bridgeパターンを使用しない例 AbstractDisplayOrnament.h #include <string>
#include "IDisplay.h"
class AbstractDisplayOrnament : public IDisplay
{
public:
AbstractDisplayOrnament(void);
virtual ~AbstractDisplayOrnament(void);
void AbstractDisplayOrnament(std::string);
};
AbstractDisplayOrnament.cpp #include <iostream>
using namespace std;
#include "AbstractDisplayOrnament.h"
AbstractDisplayOrnament::AbstractDisplayOrnament(void) {}
AbstractDisplayOrnament::~AbstractDisplayOrnament(void) {}
void AbstractDisplayOrnament::displayOrnament(string str) {
cout << "[";
display(str);
cout << "]" << endl;
}
DisplayOrnamentLowercase.h #include <string>
#include "DisplayOrnament.h"
class DisplayOrnamentLowercase : public AbstractDisplayOrnament
{
public:
DisplayOrnamentLowercase(void);
virtual ~DisplayOrnamentLowercase(void);
void display(std::string);
};
DisplayOrnamentLowercase.cpp #include <iostream>
using namespace std;
#include <algorithm>
#include "DisplayOrnamentLowercase.h"
DisplayOrnamentLowercase::DisplayOrnamentLowercase(void) {}
DisplayOrnamentLowercase::~DisplayOrnamentLowercase(void) {}
void DisplayOrnamentLowercase::display(string str) {
transform(str.begin(), str.end(), str.begin(), tolower);
cout << str;
}
DisplayOrnamentUppercase.h #include <string>
#include "DisplayOrnament.h"
class DisplayOrnamentUppercase : public AbstractDisplayOrnament
{
public:
DisplayOrnamentUppercase(void);
virtual ~DisplayOrnamentUppercase(void);
void display(std::string);
};
DisplayOrnamentUppercase.cpp #include <iostream>
using namespace std;
#include <algorithm>
#include "DisplayOrnamentUppercase.h"
DisplayOrnamentUppercase::DisplayOrnamentUppercase(void) {}
DisplayOrnamentUppercase::~DisplayOrnamentUppercase(void) {}
void DisplayOrnamentUppercase::display(string str) {
transform(str.begin(), str.end(), str.begin(), toupper);
cout << str;
}
main.cpp #include <iostream>
using namespace std;
#include "DisplayLowercase.h"
#include "DisplayUppercase.h"
#include "DisplayOrnamentLowercase.h"
int main() {
DisplayUppercase dispU;
dispU.display("AbCdEfGh"); cout << endl;
DisplayLowercase dispL;
dispL.display("AbCdEfGh"); cout << endl;
DisplayOrnamentLowercase dispOL;
dispOL.display("AbCdEfGh"); cout << endl;
dispOL.displayOrnament("AbCdEfGh"); cout << endl;
return 0;
}
|
Bridgeパターンを使用した例 DisplayNormal.h #include <string>
#include "IDisplay.h"
class DisplayNormal
{
private:
IDisplay* displayImplement;
public:
DisplayNormal(void);
DisplayNormal(IDisplay*);
virtual ~Display(void);
void display(std::string);
};
DisplayNormal.cpp #include "DisplayNormal.h"
using namespace std;
DisplayNormal::DisplayNormal(void) {}
DisplayNormal::DisplayNormal(IDisplay* dispImp) : displayImplement(dispImp) {}
DisplayNormal::~DisplayNormal(void) {}
void DisplayNormal::display(string str) {
displayImplement->display(str);
}
DisplayOrnament.h #include "IDisplay.h"
#include "DisplayNormal.h"
class DisplayOrnament : public DisplayNormal
{
public:
DisplayOrnament(void);
DisplayOrnament(IDisplay*);
virtual ~DisplayOrnament(void);
void displayOrnament(std::string);
};
DisplayOrnament.cpp #include <iostream>
using namespace std;
#include "DisplayOrnament.h"
DisplayOrnament::DisplayOrnament(void) {}
DisplayOrnament::DisplayOrnament(IDisplay* dispImp) : Display(dispImp) {}
OrnamentView::~OrnamentView(void) {}
void OrnamentView::displayOrnament(string str) {
cout << "[";
display(str);
cout << "]";
}
main.cpp #include <iostream>
using namespace std;
#include "IDisplay.h"
#include "DisplayUppercase.h"
#include "DisplayLowercase.h"
#include "DisplayOrnament.h"
int main() {
DisplayUppercase upper;
DisplayNormal dispU(&upper);
dispU.display("AbCdEfGh"); cout << endl;
DisplayLowercase lower;
DisplayNormal dispL(&lower);
dispL.display("AbCdEfGh"); cout << endl;
DisplayOrnament dispOU(&upper);
dispOU.display("AbCdEfGh"); cout << endl;
dispOU.displayOrnament("AbCdEfGh"); cout << endl;
return 0;
}
|
|
大文字で表示する DisplayUppercase、小文字で表示する DisplayLowercase があるにもかかわらず、[] で囲む DisplayOrnamentUppercase や DisplayOrnamentLowercase の中にも大文字や小文字にする機能を作らなければなりません。 よって、(大文字小文字の2種類)×(修飾有り無しの2種類)分のクラスが必要になります。 |
Bridge パターンでは、実装の変更が考えられるメソッドに関しては、実装用のクラス階層に委譲するように設計します。実装用のクラス階層とは、ここでは display メソッドの実装を与えるクラス階層として、IDisplay インタフェースをインプリメントするクラス階層を考えます。具体的には、Display クラス、 IDisplay インタフェースをコーディング例のようにしておきます。 Display クラスは、コンストラクタで、引数とした渡された、大文字や小文字で表示するクラスのインスタンスをdisplayImplement に保存し、display メソッドで、そのインスタンスのdisplayメソッドを呼び出します。そして、[ ] で囲むクラスのスーパークラスとなります。 IDisplay は、大文字や小文字で表示するクラスに共通するインタフェースとなります。 そして、実際に大文字や小文字に変換する機能を実装する DisplayUppercase クラスと DisplayLowercase クラスを IDisplay インタフェースをインプリメントしたクラスとして作成するようにします。 このような設計にしておくと、機能を追加するために、 Display クラスを継承して作成した新しいクラスでも、すでに存在する実装部分を利用することができるようになります。例えば、 Display クラスを継承して、[]で囲んで表示できるようにした DisplayOrnament クラスです。すでに存在している、大文字や小文字で表示する機能を利用できるのです。 例えば、DisplayUppercase のインスタンスを引数に DisplayOrnament のインスタンスを生成します(displayImplement に DisplayUppercase のインスタンスが保存されます)。そして、そのインスタンスの displayOrnament メソッドを呼び出せば、“[” の表示に続いて、(DisplayOrnament のスーパークラスである Display の display メソッドが呼び出され、displayImplement に保存されているインスタンス、すなわち)DisplayUppercase のdisplay メソッドが呼び出され、文字列が大文字で表示されます。そして、“]” の表示がされます。 このように、機能を拡張するためのクラス階層と、実装を拡張するためのクラス階層を分けておくことで、実装階層クラスと機能拡張クラスを好みの組み合わせで利用することができるようになります。今回の例では、 IDisplay インタフェースと Display クラスが機能拡張クラス階層と実装拡張クラス階層を橋渡しする役目を果たしています。 |
共通クラス
|
Bridgeパターンを使用しない例 DisplayOrnament.cs abstract class DisplayOrnament : IDisplay
{
public void Display_Ornament(string str)
{
Console.Write("[");
Display(str);
Console.Write("]");
}
public abstract void Display(string str);
}
DisplayOrnamentLowercase.cs class DisplayOrnamentLowercase : DisplayOrnament
{
public override void Display(string str)
{
Console.Write(str.ToLower());
}
}
DisplayOrnamentUppercase.cs class DisplayOrnamentUppercase : DisplayOrnament
{
public override void Display(string str)
{
Console.Write(str.ToUpper());
}
}
Program.cs class Program
{
static void Main(string[] args)
{
IDisplay dispU = new DisplayUppercase();
dispU.Display("AbCdEfGh"); Console.WriteLine();
IDisplay dispL = new DisplayLowercase();
dispL.Display("AbCdEfGh"); Console.WriteLine();
DisplayOrnament dispOU = new DisplayOrnamentUppercase();
dispOU.Display("AbCdEfGh"); Console.WriteLine();
dispOU.Display_Ornament("AbCdEfGh"); Console.WriteLine();
}
}
|
Bridgeパターンを使用した例 DisplayNormal.cs class DisplayNormal
{
private IDisplay displayImplement;
public DisplayNormal(IDisplay dispImp)
{
this.displayImplement = dispImp;
}
public void Display(string str)
{
displayImplement.Display(str);
}
}
DisplayOrnament.cs class DisplayOrnament : DisplayNormal
{
public DisplayOrnament(IDisplay disp) : base(disp) {}
public void Display_Ornament(string str)
{
Console.Write("[");
Display(str);
Console.Write("]");
}
}
Program.cs class Program
{
static void Main(string[] args)
{
DisplayNormal dispU = new DisplayNormal(new DisplayUppercase());
dispU.Display("AbCdEfGh"); Console.WriteLine();
DisplayNormal dispL = new DisplayNormal(new DisplayLowercase());
dispL.Display("AbCdEfGh"); Console.WriteLine();
DisplayOrnament dispOU = new DisplayOrnament(new DisplayUppercase());
dispOU.Display("AbCdEfGh"); Console.WriteLine();
dispOU.Display_Ornament("AbCdEfGh"); Console.WriteLine();
}
}
|
|
大文字で表示する DisplayUppercase、小文字で表示する DisplayLowercase があるにもかかわらず、[] で囲む DisplayOrnamentUppercase や DisplayOrnamentLowercase の中にも大文字や小文字にする機能を作らなければなりません。 よって、(大文字小文字の2種類)×(修飾有り無しの2種類)分のクラスが必要になります。 |
Bridge パターンでは、実装の変更が考えられるメソッドに関しては、実装用のクラス階層に委譲するように設計します。実装用のクラス階層とは、ここでは display メソッドの実装を与えるクラス階層として、IDisplay インタフェースをインプリメントするクラス階層を考えます。具体的には、Display クラス、 IDisplay インタフェースをコーディング例のようにしておきます。 Display クラスは、コンストラクタで、引数とした渡された、大文字や小文字で表示するクラスのインスタンスをdisplayImplement に保存し、display メソッドで、そのインスタンスのdisplayメソッドを呼び出します。そして、[ ] で囲むクラスのスーパークラスとなります。 IDisplay は、大文字や小文字で表示するクラスに共通するインタフェースとなります。 そして、実際に大文字や小文字に変換する機能を実装する DisplayUppercase クラスと DisplayLowercase クラスを IDisplay インタフェースをインプリメントしたクラスとして作成するようにします。 このような設計にしておくと、機能を追加するために、 Display クラスを継承して作成した新しいクラスでも、すでに存在する実装部分を利用することができるようになります。例えば、 Display クラスを継承して、[]で囲んで表示できるようにした DisplayOrnament クラスです。すでに存在している、大文字や小文字で表示する機能を利用できるのです。 例えば、DisplayUppercase のインスタンスを引数に DisplayOrnament のインスタンスを生成します(displayImplement に DisplayUppercase のインスタンスが保存されます)。そして、そのインスタンスの displayOrnament メソッドを呼び出せば、“[” の表示に続いて、(DisplayOrnament のスーパークラスである Display の display メソッドが呼び出され、displayImplement に保存されているインスタンス、すなわち)DisplayUppercase のdisplay メソッドが呼び出され、文字列が大文字で表示されます。そして、“]” の表示がされます。 このように、機能を拡張するためのクラス階層と、実装を拡張するためのクラス階層を分けておくことで、実装階層クラスと機能拡張クラスを好みの組み合わせで利用することができるようになります。今回の例では、 IDisplay インタフェースと Display クラスが機能拡張クラス階層と実装拡張クラス階層を橋渡しする役目を果たしています。 |
既存クラス
|
Bridgeパターンを使用しない例 DisplayOrnament.vb Public MustInherit Class DisplayOrnament
Implements IDisplay
Public Sub DisplayOrnament(ByVal str As String)
Console.Write("[")
display(str)
Console.Write("]")
End Sub
Public MustOverride Sub display(ByVal str As String) Implements IDisplay.Display
End Class
DisplayOrnamentLowercase.vb Public Class DisplayOrnamentLowercase
Inherits DisplayOrnament
Public Overrides Sub Display(ByVal str As String)
Console.Write(str.ToLower())
End Sub
End Class
DisplayOrnamentUppercase.vb Public Class DisplayOrnamentUppercase
Inherits DisplayOrnament
Public Overrides Sub Display(ByVal str As String)
Console.Write(str.ToUpper())
End Sub
End Class
Program.vb Module Main
Sub Main()
Dim dispU As IDisplay = New DisplayOrnamentUppercase()
dispU.Display("AbCdEfGh") : Console.WriteLine()
Dim dispL As IDisplay = New DisplayOrnamentLowercase()
dispL.Display("AbCdEfGh") : Console.WriteLine()
Dim dispOU As DisplayOrnament = New DisplayOrnamentUppercase()
dispOU.display("AbCdEfGh") : Console.WriteLine()
dispOU.DisplayOrnament("AbCdEfGh") : Console.WriteLine()
End Sub
End Module
|
Bridgeパターンを使用した例 DisplayNormal.vb Public Class DisplayNormal
Private displayImplement As IDisplay
Public Sub New(dispImp As IDisplay)
displayImplement = dispImp
End Sub
Public Sub Display(ByVal str As String)
displayImplement.Display(str)
End Sub
End Class
DisplayOrnament.vb Public Class DisplayOrnament
Inherits DisplayNormal
Public Sub New(disp As IDisplay)
MyBase.New(disp)
End Sub
Public Sub DisplayOrnament(str As String)
Console.Write("[")
Display(str)
Console.Write("]")
End Sub
End Class
Program.vb Module Main
Sub Main()
Dim dispU As DisplayNormal = New DisplayNormal(New DisplayUppercase())
dispU.Display("AbCdEfGh") : Console.WriteLine()
Dim dispL As DisplayNormal = New DisplayNormal(New DisplayLowercase())
dispL.Display("AbCdEfGh") : Console.WriteLine()
Dim dispOU As DisplayOrnament = New DisplayOrnament(New DisplayUppercase())
dispOU.Display("AbCdEfGh") : Console.WriteLine()
dispOU.DisplayOrnament("AbCdEfGh") : Console.WriteLine()
End Sub
End Module
|
|
大文字で表示する DisplayUppercase、小文字で表示する DisplayLowercase があるにもかかわらず、[] で囲む DisplayOrnamentUppercase や DisplayOrnamentLowercase の中にも大文字や小文字にする機能を作らなければなりません。 よって、(大文字小文字の2種類)×(修飾有り無しの2種類)分のクラスが必要になります。 |
Bridge パターンでは、実装の変更が考えられるメソッドに関しては、実装用のクラス階層に委譲するように設計します。実装用のクラス階層とは、ここでは display メソッドの実装を与えるクラス階層として、IDisplay インタフェースをインプリメントするクラス階層を考えます。具体的には、Display クラス、 IDisplay インタフェースをコーディング例のようにしておきます。 Display クラスは、コンストラクタで、引数とした渡された、大文字や小文字で表示するクラスのインスタンスをdisplayImplement に保存し、display メソッドで、そのインスタンスのdisplayメソッドを呼び出します。そして、[ ] で囲むクラスのスーパークラスとなります。 IDisplay は、大文字や小文字で表示するクラスに共通するインタフェースとなります。 そして、実際に大文字や小文字に変換する機能を実装する DisplayUppercase クラスと DisplayLowercase クラスを IDisplay インタフェースをインプリメントしたクラスとして作成するようにします。 このような設計にしておくと、機能を追加するために、 Display クラスを継承して作成した新しいクラスでも、すでに存在する実装部分を利用することができるようになります。例えば、 Display クラスを継承して、[]で囲んで表示できるようにした DisplayOrnament クラスです。すでに存在している、大文字や小文字で表示する機能を利用できるのです。 例えば、DisplayUppercase のインスタンスを引数に DisplayOrnament のインスタンスを生成します(displayImplement に DisplayUppercase のインスタンスが保存されます)。そして、そのインスタンスの displayOrnament メソッドを呼び出せば、“[” の表示に続いて、(DisplayOrnament のスーパークラスである Display の display メソッドが呼び出され、displayImplement に保存されているインスタンス、すなわち)DisplayUppercase のdisplay メソッドが呼び出され、文字列が大文字で表示されます。そして、“]” の表示がされます。 このように、機能を拡張するためのクラス階層と、実装を拡張するためのクラス階層を分けておくことで、実装階層クラスと機能拡張クラスを好みの組み合わせで利用することができるようになります。今回の例では、 IDisplay インタフェースと Display クラスが機能拡張クラス階層と実装拡張クラス階層を橋渡しする役目を果たしています。 |
共通クラス
|
Bridgeパターンを使用しない例 AbstractDisplayOrnament.js const IDisplay = require("./IDisplay.js");
module.exports = class AbstractDisplayOrnament extends IDisplay {
displayOrnament(str) {
process.stdout.write("[");
this.display(str);
process.stdout.write("]");
}
}
DisplayOrnamentLowercase.js const AbstractDisplayOrnament = require("./AbstractDisplayOrnament.js");
module.exports = class DisplayOrnamentLowercase extends AbstractDisplayOrnament {
display(str) {
process.stdout.write(str.toLowerCase());
}
}
DisplayOrnamentUppercase.js const AbstractDisplayOrnament = require("./AbstractDisplayOrnament.js");
module.exports = class DisplayOrnamentUppercase extends AbstractDisplayOrnament {
display(str) {
process.stdout.write(str.toUpperCase());
}
}
Main.js const DisplayLowercase = require("./DisplayLowercase.js");
const DisplayUppercase = require("./DisplayUppercase.js");
const DisplayOrnamentUppercase = require("./DisplayOrnamentUppercase.js");
let dispU = new DisplayUppercase();
dispU.display("AbCdEfGh"); process.stdout.write("\n");
let dispL = new DisplayLowercase();
dispL.display("AbCdEfGh"); process.stdout.write("\n");
let dispOU = new DisplayOrnamentUppercase();
dispOU.display("AbCdEfGh"); process.stdout.write("\n");
dispOU.displayOrnament("AbCdEfGh"); process.stdout.write("\n");
|
Bridgeパターンを使用した例 DisplayNormal.js module.exports = class DisplayNormal {
constructor(dispImp) {
this.displayImplement = dispImp;
}
display(str) {
this.displayImplement.display(str);
}
}
DisplayOrnament.js const DisplayNormal = require("./DisplayNormal.js");
module.exports = class DisplayOrnament extends DisplayNormal {
constructor(dispImp) {
super(dispImp);
}
displayOrnament(str) {
process.stdout.write("[");
this.display(str);
process.stdout.write("]");
}
}
Main.js const DisplayNormal = require("./DisplayNormal.js");
const DisplayOrnament = require("./DisplayOrnament.js");
const DisplayLowercase = require("./DisplayLowercase.js");
const DisplayUppercase = require("./DisplayUppercase.js");
let dispU = new DisplayNormal(new DisplayUppercase());
dispU.display("AbCdEfGh"); process.stdout.write("\n");
let dispL = new DisplayNormal(new DisplayLowercase());
dispL.display("AbCdEfGh"); process.stdout.write("\n");
let dispOU = new DisplayOrnament(new DisplayUppercase());
dispOU.display("AbCdEfGh"); process.stdout.write("\n");
dispOU.displayOrnament("AbCdEfGh"); process.stdout.write("\n");
|
|
大文字で表示する DisplayUppercase、小文字で表示する DisplayLowercase があるにもかかわらず、[] で囲む DisplayOrnamentUppercase や DisplayOrnamentLowercase の中にも大文字や小文字にする機能を作らなければなりません。 よって、(大文字小文字の2種類)×(修飾有り無しの2種類)分のクラスが必要になります。 |
Bridge パターンでは、実装の変更が考えられるメソッドに関しては、実装用のクラス階層に委譲するように設計します。実装用のクラス階層とは、ここでは display メソッドの実装を与えるクラス階層として、IDisplay インタフェースをインプリメントするクラス階層を考えます。具体的には、Display クラス、 IDisplay インタフェースをコーディング例のようにしておきます。 Display クラスは、コンストラクタで、引数とした渡された、大文字や小文字で表示するクラスのインスタンスをdisplayImplement に保存し、display メソッドで、そのインスタンスのdisplayメソッドを呼び出します。そして、[ ] で囲むクラスのスーパークラスとなります。 IDisplay は、大文字や小文字で表示するクラスに共通するインタフェースとなります。 そして、実際に大文字や小文字に変換する機能を実装する DisplayUppercase クラスと DisplayLowercase クラスを IDisplay インタフェースをインプリメントしたクラスとして作成するようにします。 このような設計にしておくと、機能を追加するために、 Display クラスを継承して作成した新しいクラスでも、すでに存在する実装部分を利用することができるようになります。例えば、 Display クラスを継承して、[]で囲んで表示できるようにした DisplayOrnament クラスです。すでに存在している、大文字や小文字で表示する機能を利用できるのです。 例えば、DisplayUppercase のインスタンスを引数に DisplayOrnament のインスタンスを生成します(displayImplement に DisplayUppercase のインスタンスが保存されます)。そして、そのインスタンスの displayOrnament メソッドを呼び出せば、“[” の表示に続いて、(DisplayOrnament のスーパークラスである Display の display メソッドが呼び出され、displayImplement に保存されているインスタンス、すなわち)DisplayUppercase のdisplay メソッドが呼び出され、文字列が大文字で表示されます。そして、“]” の表示がされます。 このように、機能を拡張するためのクラス階層と、実装を拡張するためのクラス階層を分けておくことで、実装階層クラスと機能拡張クラスを好みの組み合わせで利用することができるようになります。今回の例では、 IDisplay インタフェースと Display クラスが機能拡張クラス階層と実装拡張クラス階層を橋渡しする役目を果たしています。 |
共通クラス
|
Bridgeパターンを使用しない例 AbstractDisplayOrnament.pm package AbstractDisplayOrnament {
use base qw(IDisplay);
sub new {
my ($class) = @_;
my $this = $class->SUPER::new();
return bless $this, $class;
}
sub displayOrnament {
my ($this, $str) = @_;
print "[";
$this->display($str);
print "]";
}
}
1;
DisplayOrnamentLowercase.pm package DisplayOrnamentLowercase {
use base qw(AbstractDisplayOrnament);
sub new {
my ($class) = @_;
my $this = $class->SUPER::new();
return bless $this, $class;
}
sub display {
my ($this, $str) = @_;
print lc $str;
}
}
1;
DisplayOrnamentUppercase.pm package DisplayOrnamentUppercase {
use base qw(AbstractDisplayOrnament);
sub new {
my ($class) = @_;
my $this = $class->SUPER::new();
return bless $this, $class;
}
sub display {
my ($this, $str) = @_;
print uc $str;
}
}
1;
Main.pl use lib qw(./);
use DisplayLowercase;
use DisplayUppercase;
use DisplayOrnamentUppercase;
my $dispU = new DisplayUppercase();
$dispU->display("AbCdEfGh"); print "\n";
my $dispL = new DisplayLowercase();
$dispL->display("AbCdEfGh"); print "\n";
my $dispOU = new DisplayOrnamentUppercase();
$dispOU->display("AbCdEfGh"); print "\n";
$dispOU->displayOrnament("AbCdEfGh"); print "\n";
|
Bridgeパターンを使用した例 DisplayNormal.pm package DisplayNormal {
sub new {
my ($class, $dispImp) = @_;
my $this = { displayImplement => $dispImp };
return bless $this, $class;
}
sub display {
my ($this, $str) = @_;
$this->{displayImplement}->display($str);
}
}
1;
DisplayOrnament.pm package DisplayOrnament {
use base qw(DisplayNormal);
sub new() {
my ($class, $dispImp) = @_;
my $this = $class->SUPER::new($dispImp);
return bless $this, $class;
}
sub displayOrnament {
my ($this, $str) = @_;
print "[";
$this->display($str);
print "]";
}
}
1;
Main.pl use lib qw(./);
use DisplayNormal;
use DisplayOrnament;
use DisplayLowercase;
use DisplayUppercase;
my $dispU = new DisplayNormal(new DisplayUppercase());
$dispU->display("AbCdEfGh"); print "\n";
my $dispL = new DisplayNormal(new DisplayLowercase());
$dispL->display("AbCdEfGh"); print "\n";
my $dispOU = new DisplayOrnament(new DisplayUppercase());
$dispOU->display("AbCdEfGh"); print "\n";
$dispOU->displayOrnament("AbCdEfGh"); print "\n";
|
|
大文字で表示する DisplayUppercase、小文字で表示する DisplayLowercase があるにもかかわらず、[] で囲む DisplayOrnamentUppercase や DisplayOrnamentLowercase の中にも大文字や小文字にする機能を作らなければなりません。 よって、(大文字小文字の2種類)×(修飾有り無しの2種類)分のクラスが必要になります。 |
Bridge パターンでは、実装の変更が考えられるメソッドに関しては、実装用のクラス階層に委譲するように設計します。実装用のクラス階層とは、ここでは display メソッドの実装を与えるクラス階層として、IDisplay インタフェースをインプリメントするクラス階層を考えます。具体的には、Display クラス、 IDisplay インタフェースをコーディング例のようにしておきます。 Display クラスは、コンストラクタで、引数とした渡された、大文字や小文字で表示するクラスのインスタンスをdisplayImplement に保存し、display メソッドで、そのインスタンスのdisplayメソッドを呼び出します。そして、[ ] で囲むクラスのスーパークラスとなります。 IDisplay は、大文字や小文字で表示するクラスに共通するインタフェースとなります。 そして、実際に大文字や小文字に変換する機能を実装する DisplayUppercase クラスと DisplayLowercase クラスを IDisplay インタフェースをインプリメントしたクラスとして作成するようにします。 このような設計にしておくと、機能を追加するために、 Display クラスを継承して作成した新しいクラスでも、すでに存在する実装部分を利用することができるようになります。例えば、 Display クラスを継承して、[]で囲んで表示できるようにした DisplayOrnament クラスです。すでに存在している、大文字や小文字で表示する機能を利用できるのです。 例えば、DisplayUppercase のインスタンスを引数に DisplayOrnament のインスタンスを生成します(displayImplement に DisplayUppercase のインスタンスが保存されます)。そして、そのインスタンスの displayOrnament メソッドを呼び出せば、“[” の表示に続いて、(DisplayOrnament のスーパークラスである Display の display メソッドが呼び出され、displayImplement に保存されているインスタンス、すなわち)DisplayUppercase のdisplay メソッドが呼び出され、文字列が大文字で表示されます。そして、“]” の表示がされます。 このように、機能を拡張するためのクラス階層と、実装を拡張するためのクラス階層を分けておくことで、実装階層クラスと機能拡張クラスを好みの組み合わせで利用することができるようになります。今回の例では、 IDisplay インタフェースと Display クラスが機能拡張クラス階層と実装拡張クラス階層を橋渡しする役目を果たしています。 |
共通クラス
|
Bridgeパターンを使用しない例 AbstractDisplayOrnament.rb require './IDisplay'
class AbstractDisplayOrnament < IDisplay
def displayOrnament(str)
print "["
display(str)
print "]"
end
end
DisplayOrnamentLowercase.rb require './AbstractDisplayOrnament'
class DisplayOrnamentLowercase < AbstractDisplayOrnament
display(str)
print str.downcase()
end
end
DisplayOrnamentUppercase.rb require './AbstractDisplayOrnament'
class DisplayOrnamentUppercase < AbstractDisplayOrnament
display(str)
print str.upcase()
end
end
Main.rb require './DisplayLowercase'
require './DisplayUppercase'
require './DisplayOrnamentUppercase'
dispU = DisplayUppercase.new()
dispU.display("AbCdEfGh")
puts ""
dispL = DisplayLowercase.new()
dispL.display("AbCdEfGh")
puts ""
dispOU = DisplayOrnamentUppercase.new()
dispOU.display("AbCdEfGh")
puts ""
dispOU.displayOrnament("AbCdEfGh")
puts ""
|
Bridgeパターンを使用した例 DisplayNormal.rb class DisplayNormal
def initialize(dispImp)
@displayImplement = dispImp
end
def display(str)
@displayImplement.display(str)
end
end
DisplayOrnament.rb require './DisplayNormal'
class DisplayOrnament < DisplayNormal
def initialize(dispImp)
super(dispImp)
end
def displayOrnament(str)
print "["
display(str)
print "]"
end
end
Main.rb require './DisplayNormal'
require './DisplayOrnament'
require './DisplayLowercase'
require './DisplayUppercase'
dispU = DisplayNormal.new(DisplayUppercase.new())
dispU.display("AbCdEfGh")
puts ""
dispL = DisplayNormal.new(DisplayLowercase.new())
dispL.display("AbCdEfGh")
puts ""
dispOU = DisplayOrnament.new(DisplayUppercase.new());
dispOU.display("AbCdEfGh")
puts ""
dispOU.displayOrnament("AbCdEfGh")
puts ""
|
|
大文字で表示する DisplayUppercase、小文字で表示する DisplayLowercase があるにもかかわらず、[] で囲む DisplayOrnamentUppercase や DisplayOrnamentLowercase の中にも大文字や小文字にする機能を作らなければなりません。 よって、(大文字小文字の2種類)×(修飾有り無しの2種類)分のクラスが必要になります。 |
Bridge パターンでは、実装の変更が考えられるメソッドに関しては、実装用のクラス階層に委譲するように設計します。実装用のクラス階層とは、ここでは display メソッドの実装を与えるクラス階層として、IDisplay インタフェースをインプリメントするクラス階層を考えます。具体的には、Display クラス、 IDisplay インタフェースをコーディング例のようにしておきます。 Display クラスは、コンストラクタで、引数とした渡された、大文字や小文字で表示するクラスのインスタンスをdisplayImplement に保存し、display メソッドで、そのインスタンスのdisplayメソッドを呼び出します。そして、[ ] で囲むクラスのスーパークラスとなります。 IDisplay は、大文字や小文字で表示するクラスに共通するインタフェースとなります。 そして、実際に大文字や小文字に変換する機能を実装する DisplayUppercase クラスと DisplayLowercase クラスを IDisplay インタフェースをインプリメントしたクラスとして作成するようにします。 このような設計にしておくと、機能を追加するために、 Display クラスを継承して作成した新しいクラスでも、すでに存在する実装部分を利用することができるようになります。例えば、 Display クラスを継承して、[]で囲んで表示できるようにした DisplayOrnament クラスです。すでに存在している、大文字や小文字で表示する機能を利用できるのです。 例えば、DisplayUppercase のインスタンスを引数に DisplayOrnament のインスタンスを生成します(displayImplement に DisplayUppercase のインスタンスが保存されます)。そして、そのインスタンスの displayOrnament メソッドを呼び出せば、“[” の表示に続いて、(DisplayOrnament のスーパークラスである Display の display メソッドが呼び出され、displayImplement に保存されているインスタンス、すなわち)DisplayUppercase のdisplay メソッドが呼び出され、文字列が大文字で表示されます。そして、“]” の表示がされます。 このように、機能を拡張するためのクラス階層と、実装を拡張するためのクラス階層を分けておくことで、実装階層クラスと機能拡張クラスを好みの組み合わせで利用することができるようになります。今回の例では、 IDisplay インタフェースと Display クラスが機能拡張クラス階層と実装拡張クラス階層を橋渡しする役目を果たしています。 |
共通クラス
|
Bridgeパターンを使用しない例 AbstractDisplayOrnament.py from abc import ABCMeta, abstractmethod
class AbstractDisplayOrnament(metaclass=ABCMeta):
def displayOrnament(self, str):
print("[", end="")
self.display(str)
print("]", end="")
DisplayOrnamentLowercase.py from AbstractDisplayOrnament import AbstractDisplayOrnament
class DisplayOrnamentLowercase(AbstractDisplayOrnament):
def display(self, str):
print(str.lower(), end="")
DisplayOrnamentUppercase.py from AbstractDisplayOrnament import AbstractDisplayOrnament
class DisplayOrnamentUppercase(AbstractDisplayOrnament):
def display(self, str):
print(str.upper(), end="")
Main.py from DisplayLowercase import DisplayLowercase
from DisplayUppercase import DisplayUppercase
from DisplayOrnamentUppercase import DisplayOrnamentUppercase
dispU = DisplayUppercase()
dispU.display("AbCdEfGh"); print()
dispL = DisplayLowercase()
dispL.display("AbCdEfGh"); print()
dispOU = DisplayOrnamentUppercase()
dispOU.display("AbCdEfGh"); print()
dispOU.displayOrnament("AbCdEfGh"); print()
|
Bridgeパターンを使用した例 DisplayNormal.py class DisplayNormal:
def __init__(self, dispImp):
self.displayImplement = dispImp
def display(self, str):
self.displayImplement.display(str)
DisplayOrnament.py from DisplayNormal import DisplayNormal
class DisplayOrnament(DisplayNormal):
def __init__(self, dispImp):
super().__init__(dispImp)
def displayOrnament(self, str):
print("[", end="")
self.display(str)
print("]", end="")
Main.py from DisplayNormal import DisplayNormal
from DisplayOrnament import DisplayOrnament
from DisplayLowercase import DisplayLowercase
from DisplayUppercase import DisplayUppercase
dispU = DisplayNormal(DisplayUppercase())
dispU.display("AbCdEfGh"); print()
dispL = DisplayNormal(DisplayLowercase()); print()
dispL.display("AbCdEfGh"); print()
dispOU = DisplayOrnament(DisplayUppercase())
dispOU.display("AbCdEfGh"); print()
dispOU.displayOrnament("AbCdEfGh"); print()
|
|
大文字で表示する DisplayUppercase、小文字で表示する DisplayLowercase があるにもかかわらず、[] で囲む DisplayOrnamentUppercase や DisplayOrnamentLowercase の中にも大文字や小文字にする機能を作らなければなりません。 よって、(大文字小文字の2種類)×(修飾有り無しの2種類)分のクラスが必要になります。 |
Bridge パターンでは、実装の変更が考えられるメソッドに関しては、実装用のクラス階層に委譲するように設計します。実装用のクラス階層とは、ここでは display メソッドの実装を与えるクラス階層として、IDisplay インタフェースをインプリメントするクラス階層を考えます。具体的には、Display クラス、 IDisplay インタフェースをコーディング例のようにしておきます。 Display クラスは、コンストラクタで、引数とした渡された、大文字や小文字で表示するクラスのインスタンスをdisplayImplement に保存し、display メソッドで、そのインスタンスのdisplayメソッドを呼び出します。そして、[ ] で囲むクラスのスーパークラスとなります。 IDisplay は、大文字や小文字で表示するクラスに共通するインタフェースとなります。 そして、実際に大文字や小文字に変換する機能を実装する DisplayUppercase クラスと DisplayLowercase クラスを IDisplay インタフェースをインプリメントしたクラスとして作成するようにします。 このような設計にしておくと、機能を追加するために、 Display クラスを継承して作成した新しいクラスでも、すでに存在する実装部分を利用することができるようになります。例えば、 Display クラスを継承して、[]で囲んで表示できるようにした DisplayOrnament クラスです。すでに存在している、大文字や小文字で表示する機能を利用できるのです。 例えば、DisplayUppercase のインスタンスを引数に DisplayOrnament のインスタンスを生成します(displayImplement に DisplayUppercase のインスタンスが保存されます)。そして、そのインスタンスの displayOrnament メソッドを呼び出せば、“[” の表示に続いて、(DisplayOrnament のスーパークラスである Display の display メソッドが呼び出され、displayImplement に保存されているインスタンス、すなわち)DisplayUppercase のdisplay メソッドが呼び出され、文字列が大文字で表示されます。そして、“]” の表示がされます。 このように、機能を拡張するためのクラス階層と、実装を拡張するためのクラス階層を分けておくことで、実装階層クラスと機能拡張クラスを好みの組み合わせで利用することができるようになります。今回の例では、 IDisplay インタフェースと Display クラスが機能拡張クラス階層と実装拡張クラス階層を橋渡しする役目を果たしています。 |
共通クラス
|
Bridgeパターンを使用しない例 AbstractDisplayOrnament.php <?php
require_once('IDisplay.php');
abstract class AbstractDisplayOrnament implements IDisplay {
public function displayOrnament($str) {
print "[";
$this->display($str);
print "]";
}
}
?>
DisplayOrnamentLowercase.php <?php
require_once('AbstractDisplayOrnament.php');
class DisplayOrnamentLowercase extends AbstractDisplayOrnament {
public function display($str) {
print strtolower($str);
}
}
?>
DisplayOrnamentUppercase.php <?php
require_once('AbstractDisplayOrnament.php');
public class DisplayOrnamentUppercase extends AbstractDisplayOrnament {
public function display($str) {
print strtoupper($str);
}
}
?>
Main.php <?php
require_once('DisplayUppercase.php');
require_once('DisplayLowercase.php');
require_once('DisplayOrnamentUppercase.php');
$dispU = new DisplayUppercase();
$dispU->display("AbCdEfGh"); print "\n";
$dispL = new DisplayLowercase();
$dispL->display("AbCdEfGh"); print "\n";
$dispOU = new DisplayOrnamentUppercase();
$dispOU->display("AbCdEfGh"); print "\n";
$dispOU->displayOrnament("AbCdEfGh"); print "\n";
?>
|
Bridgeパターンを使用した例 DisplayNormal.php <?php
public class DisplayNormal {
public function __construct($dispImp) {
$this->displayImplement = $dispImp;
}
public function display($str) {
$this->displayImplement->display($str);
}
}
?>
DisplayOrnament.php <?php
require_once('DisplayNormal.php');
class DisplayOrnament extends DisplayNormal {
public function __construct($dispImp) {
parent::__construct($dispImp);
}
public function displayOrnament($str) {
print "[";
$this->display($str);
print "]";
}
}
?>
Main.php <?php
require_once('DisplayNormal.php');
require_once('DisplayLowercase.php');
require_once('DisplayUppercase.php');
require_once('DisplayOrnament.php');
$dispU = new DisplayNormal(new DisplayUppercase());
$dispU->display("AbCdEfGh"); print "\n";
$dispL = new DisplayNormal(new DisplayLowercase());
$dispL->display("AbCdEfGh"); print "\n";
$dispOU =new DisplayOrnament(new DisplayUppercase());
$dispOU->display("AbCdEfGh"); print "\n";
$dispOU->displayOrnament("AbCdEfGh"); print "\n";
?>
|
|
大文字で表示する DisplayUppercase、小文字で表示する DisplayLowercase があるにもかかわらず、[] で囲む DisplayOrnamentUppercase や DisplayOrnamentLowercase の中にも大文字や小文字にする機能を作らなければなりません。 よって、(大文字小文字の2種類)×(修飾有り無しの2種類)分のクラスが必要になります。 |
Bridge パターンでは、実装の変更が考えられるメソッドに関しては、実装用のクラス階層に委譲するように設計します。実装用のクラス階層とは、ここでは display メソッドの実装を与えるクラス階層として、IDisplay インタフェースをインプリメントするクラス階層を考えます。具体的には、Display クラス、 IDisplay インタフェースをコーディング例のようにしておきます。 Display クラスは、コンストラクタで、引数とした渡された、大文字や小文字で表示するクラスのインスタンスをdisplayImplement に保存し、display メソッドで、そのインスタンスのdisplayメソッドを呼び出します。そして、[ ] で囲むクラスのスーパークラスとなります。 IDisplay は、大文字や小文字で表示するクラスに共通するインタフェースとなります。 そして、実際に大文字や小文字に変換する機能を実装する DisplayUppercase クラスと DisplayLowercase クラスを IDisplay インタフェースをインプリメントしたクラスとして作成するようにします。 このような設計にしておくと、機能を追加するために、 Display クラスを継承して作成した新しいクラスでも、すでに存在する実装部分を利用することができるようになります。例えば、 Display クラスを継承して、[]で囲んで表示できるようにした DisplayOrnament クラスです。すでに存在している、大文字や小文字で表示する機能を利用できるのです。 例えば、DisplayUppercase のインスタンスを引数に DisplayOrnament のインスタンスを生成します(displayImplement に DisplayUppercase のインスタンスが保存されます)。そして、そのインスタンスの displayOrnament メソッドを呼び出せば、“[” の表示に続いて、(DisplayOrnament のスーパークラスである Display の display メソッドが呼び出され、displayImplement に保存されているインスタンス、すなわち)DisplayUppercase のdisplay メソッドが呼び出され、文字列が大文字で表示されます。そして、“]” の表示がされます。 このように、機能を拡張するためのクラス階層と、実装を拡張するためのクラス階層を分けておくことで、実装階層クラスと機能拡張クラスを好みの組み合わせで利用することができるようになります。今回の例では、 IDisplay インタフェースと Display クラスが機能拡張クラス階層と実装拡張クラス階層を橋渡しする役目を果たしています。 |
共通クラス
|
Bridgeパターンを使用しない例 AbstractDisplayOrnament.ts import {IDisplay} from "./IDisplay";
export
abstract class AbstractDisplayOrnament implements IDisplay {
public displayOrnament(str:string):void {
process.stdout.write("[");
this.display(str);
process.stdout.write("]");
}
public abstract display(str:string):void;
}
DisplayOrnamentLowercase.ts import {AbstractDisplayOrnament} from "./AbstractDisplayOrnament";
export
class DisplayOrnamentLowercase extends AbstractDisplayOrnament {
public display(str:string):void {
process.stdout.write(str.toLowerCase());
}
}
DisplayOrnamentUppercase.ts import {AbstractDisplayOrnament} from "./AbstractDisplayOrnament";
export
class DisplayOrnamentUppercase extends AbstractDisplayOrnament {
public display(str:string):void {
process.stdout.write(str.toUpperCase());
}
}
Main.ts import {DisplayLowercase} from "./DisplayLowercase";
import {DisplayUppercase} from "./DisplayUppercase";
import {DisplayOrnamentUppercase} from "./DisplayOrnamentUppercase";
import {IDisplay} from "./IDisplay";
import {AbstractDisplayOrnament} from "./AbstractDisplayOrnament";
let dispU:IDisplay = new DisplayUppercase();
dispU.display("AbCdEfGh"); process.stdout.write("\n");
let dispL:IDisplay = new DisplayLowercase();
dispL.display("AbCdEfGh"); process.stdout.write("\n");
let dispOU:AbstractDisplayOrnament = new DisplayOrnamentUppercase();
dispOU.display("AbCdEfGh"); process.stdout.write("\n");
dispOU.displayOrnament("AbCdEfGh"); process.stdout.write("\n");
|
Bridgeパターンを使用した例 DisplayNormal.ts import {IDisplay} from "./IDisplay";
export
class DisplayNormal {
private displayImplement:IDisplay;
public constructor(dispImp:IDisplay) {
this.displayImplement = dispImp;
}
public display(str:string):void {
this.displayImplement.display(str);
}
}
DisplayOrnament.ts import {DisplayNormal} from "./DisplayNormal";
import {IDisplay} from "./IDisplay";
export
class DisplayOrnament extends DisplayNormal {
public constructor(dispImp:IDisplay) {
super(dispImp);
}
public displayOrnament(str:string):void {
process.stdout.write("[");
this.display(str);
process.stdout.write("]");
}
}
Main.ts import {IDisplay} from "./IDisplay";
import {DisplayNormal} from "./DisplayNormal";
import {DisplayOrnament} from "./DisplayOrnament";
import {DisplayLowercase} from "./DisplayLowercase";
import {DisplayUppercase} from "./DisplayUppercase";
let dispU:DisplayNormal = new DisplayNormal(new DisplayUppercase());
dispU.display("AbCdEfGh"); process.stdout.write("\n");
let dispL:DisplayNormal = new DisplayNormal(new DisplayLowercase());
dispL.display("AbCdEfGh"); process.stdout.write("\n");
let dispOU:DisplayOrnament = new DisplayOrnament(new DisplayUppercase());
dispOU.display("AbCdEfGh"); process.stdout.write("\n");
dispOU.displayOrnament("AbCdEfGh"); process.stdout.write("\n");
|
|
大文字で表示する DisplayUppercase、小文字で表示する DisplayLowercase があるにもかかわらず、[] で囲む DisplayOrnamentUppercase や DisplayOrnamentLowercase の中にも大文字や小文字にする機能を作らなければなりません。 よって、(大文字小文字の2種類)×(修飾有り無しの2種類)分のクラスが必要になります。 |
Bridge パターンでは、実装の変更が考えられるメソッドに関しては、実装用のクラス階層に委譲するように設計します。実装用のクラス階層とは、ここでは display メソッドの実装を与えるクラス階層として、IDisplay インタフェースをインプリメントするクラス階層を考えます。具体的には、Display クラス、 IDisplay インタフェースをコーディング例のようにしておきます。 Display クラスは、コンストラクタで、引数とした渡された、大文字や小文字で表示するクラスのインスタンスをdisplayImplement に保存し、display メソッドで、そのインスタンスのdisplayメソッドを呼び出します。そして、[ ] で囲むクラスのスーパークラスとなります。 IDisplay は、大文字や小文字で表示するクラスに共通するインタフェースとなります。 そして、実際に大文字や小文字に変換する機能を実装する DisplayUppercase クラスと DisplayLowercase クラスを IDisplay インタフェースをインプリメントしたクラスとして作成するようにします。 このような設計にしておくと、機能を追加するために、 Display クラスを継承して作成した新しいクラスでも、すでに存在する実装部分を利用することができるようになります。例えば、 Display クラスを継承して、[]で囲んで表示できるようにした DisplayOrnament クラスです。すでに存在している、大文字や小文字で表示する機能を利用できるのです。 例えば、DisplayUppercase のインスタンスを引数に DisplayOrnament のインスタンスを生成します(displayImplement に DisplayUppercase のインスタンスが保存されます)。そして、そのインスタンスの displayOrnament メソッドを呼び出せば、“[” の表示に続いて、(DisplayOrnament のスーパークラスである Display の display メソッドが呼び出され、displayImplement に保存されているインスタンス、すなわち)DisplayUppercase のdisplay メソッドが呼び出され、文字列が大文字で表示されます。そして、“]” の表示がされます。 このように、機能を拡張するためのクラス階層と、実装を拡張するためのクラス階層を分けておくことで、実装階層クラスと機能拡張クラスを好みの組み合わせで利用することができるようになります。今回の例では、 IDisplay インタフェースと Display クラスが機能拡張クラス階層と実装拡張クラス階層を橋渡しする役目を果たしています。 |
共通クラス
|
Bridgeパターンを使用しない例 AbstractDisplayOrnament.swift public class AbstractDisplayOrnament : IDisplay {
public func displayOrnament(_ str:String) {
print("[", terminator:"")
this.display(str)
print("]")
}
public func display(_ str:String) {
fatalError("display メソッドを定義してください。")
}
}
DisplayOrnamentLowercase.swift public class DisplayOrnamentLowercase : AbstractDisplayOrnament {
public override func display(_ str:String) {
print(str.lowercased(), terminator:"")
}
}
DisplayOrnamentUppercase.swift public class DisplayOrnamentUppercase : AbstractDisplayOrnament {
public override func display(_ str:String) {
print(str.uppercased(), terminator:"")
}
}
Main.swift let dispU:IDisplay = DisplayUppercase()
dispU.display("AbCdEfGh"); print()
let dispL:IDisplay = DisplayLowercase();
dispL.display("AbCdEfGh"); print()
let dispOU:AbstractDisplayOrnament = DisplayOrnamentUppercase()
dispOU.display("AbCdEfGh"); print()
dispOU.displayOrnament("AbCdEfGh"); print()
|
Bridgeパターンを使用した例 DisplayNormal.swift public class DisplayNormal {
private var displayImplement:IDisplay
public init(_ dispImp:IDisplay) {
displayImplement = dispImp
}
public func display(_ str:String) {
displayImplement.display(str)
}
}
DisplayOrnament.swift public class DisplayOrnament : DisplayNormal {
public override init(_ dispImp:IDisplay) {
super.init(dispImp)
}
public func displayOrnament(_ str:String) {
print("[", terminator:"")
display(str)
print("]")
}
}
Main.swift let dispU:DisplayNormal = DisplayNormal(DisplayUppercase())
dispU.display("AbCdEfGh"); print()
let dispL:DisplayNormal = DisplayNormal(DisplayLowercase())
dispL.display("AbCdEfGh"); print()
let dispOU:DisplayOrnament = DisplayOrnament(DisplayUppercase())
dispOU.display("AbCdEfGh"); print()
dispOU.displayOrnament("AbCdEfGh"); print()
|
|
大文字で表示する DisplayUppercase、小文字で表示する DisplayLowercase があるにもかかわらず、[] で囲む DisplayOrnamentUppercase や DisplayOrnamentLowercase の中にも大文字や小文字にする機能を作らなければなりません。 よって、(大文字小文字の2種類)×(修飾有り無しの2種類)分のクラスが必要になります。 |
Bridge パターンでは、実装の変更が考えられるメソッドに関しては、実装用のクラス階層に委譲するように設計します。実装用のクラス階層とは、ここでは display メソッドの実装を与えるクラス階層として、IDisplay インタフェースをインプリメントするクラス階層を考えます。具体的には、Display クラス、 IDisplay インタフェースをコーディング例のようにしておきます。 Display クラスは、コンストラクタで、引数とした渡された、大文字や小文字で表示するクラスのインスタンスをdisplayImplement に保存し、display メソッドで、そのインスタンスのdisplayメソッドを呼び出します。そして、[ ] で囲むクラスのスーパークラスとなります。 IDisplay は、大文字や小文字で表示するクラスに共通するインタフェースとなります。 そして、実際に大文字や小文字に変換する機能を実装する DisplayUppercase クラスと DisplayLowercase クラスを IDisplay インタフェースをインプリメントしたクラスとして作成するようにします。 このような設計にしておくと、機能を追加するために、 Display クラスを継承して作成した新しいクラスでも、すでに存在する実装部分を利用することができるようになります。例えば、 Display クラスを継承して、[]で囲んで表示できるようにした DisplayOrnament クラスです。すでに存在している、大文字や小文字で表示する機能を利用できるのです。 例えば、DisplayUppercase のインスタンスを引数に DisplayOrnament のインスタンスを生成します(displayImplement に DisplayUppercase のインスタンスが保存されます)。そして、そのインスタンスの displayOrnament メソッドを呼び出せば、“[” の表示に続いて、(DisplayOrnament のスーパークラスである Display の display メソッドが呼び出され、displayImplement に保存されているインスタンス、すなわち)DisplayUppercase のdisplay メソッドが呼び出され、文字列が大文字で表示されます。そして、“]” の表示がされます。 このように、機能を拡張するためのクラス階層と、実装を拡張するためのクラス階層を分けておくことで、実装階層クラスと機能拡張クラスを好みの組み合わせで利用することができるようになります。今回の例では、 IDisplay インタフェースと Display クラスが機能拡張クラス階層と実装拡張クラス階層を橋渡しする役目を果たしています。 |
共通クラス
|
Bridgeパターンを使用しない例 AbstractDisplayOrnament.kt abstract class AbstractDisplayOrnament : IDisplay {
fun displayOrnament(str: String) {
print("[")
display(str)
print("]")
}
}
DisplayOrnamentLowercase.kt class DisplayOrnamentLowercase : AbstractDisplayOrnament() {
override fun display(str: String) {
print(str.toLowerCase())
}
}
DisplayOrnamentUppercase.kt class DisplayOrnamentUppercase : AbstractDisplayOrnament() {
override fun display(str: String) {
print(str.toUpperCase())
}
}
Main.kt fun main() {
val dispU: IDisplay = DisplayUppercase()
dispU.display("AbCdEfGh"); println()
val dispL:IDisplay = DisplayLowercase()
dispL.display("AbCdEfGh"); println()
val dispOU:AbstractDisplayOrnament = DisplayOrnamentUppercase()
dispOU.display("AbCdEfGh"); println()
dispOU.displayOrnament("AbCdEfGh"); println()
}
|
Bridgeパターンを使用した例 DisplayNormal.kt open class DisplayNormal(private val dispImp: IDisplay) {
fun display(str: String) {
dispImp.display(str)
}
}
DisplayOrnament.kt class DisplayOrnament(private val dispImp: IDisplay) : DisplayNormal(dispImp) {
fun displayOrnament(str: String) {
print("[")
display(str)
print("]")
}
}
Main.kt fun main() {
val dispU = DisplayNormal(DisplayUppercase())
dispU.display("AbCdEfGh"); println()
val dispL = DisplayNormal(DisplayLowercase())
dispL.display("AbCdEfGh"); println()
val dispOU = DisplayOrnament(DisplayUppercase())
dispOU.display("AbCdEfGh"); println()
dispOU.displayOrnament("AbCdEfGh"); println()
}
|
|
大文字で表示する DisplayUppercase、小文字で表示する DisplayLowercase があるにもかかわらず、[] で囲む DisplayOrnamentUppercase や DisplayOrnamentLowercase の中にも大文字や小文字にする機能を作らなければなりません。 よって、(大文字小文字の2種類)×(修飾有り無しの2種類)分のクラスが必要になります。 |
Bridge パターンでは、実装の変更が考えられるメソッドに関しては、実装用のクラス階層に委譲するように設計します。実装用のクラス階層とは、ここでは display メソッドの実装を与えるクラス階層として、IDisplay インタフェースをインプリメントするクラス階層を考えます。具体的には、Display クラス、 IDisplay インタフェースをコーディング例のようにしておきます。 Display クラスは、コンストラクタで、引数とした渡された、大文字や小文字で表示するクラスのインスタンスをdisplayImplement に保存し、display メソッドで、そのインスタンスのdisplayメソッドを呼び出します。そして、[ ] で囲むクラスのスーパークラスとなります。 IDisplay は、大文字や小文字で表示するクラスに共通するインタフェースとなります。 そして、実際に大文字や小文字に変換する機能を実装する DisplayUppercase クラスと DisplayLowercase クラスを IDisplay インタフェースをインプリメントしたクラスとして作成するようにします。 このような設計にしておくと、機能を追加するために、 Display クラスを継承して作成した新しいクラスでも、すでに存在する実装部分を利用することができるようになります。例えば、 Display クラスを継承して、[]で囲んで表示できるようにした DisplayOrnament クラスです。すでに存在している、大文字や小文字で表示する機能を利用できるのです。 例えば、DisplayUppercase のインスタンスを引数に DisplayOrnament のインスタンスを生成します(displayImplement に DisplayUppercase のインスタンスが保存されます)。そして、そのインスタンスの displayOrnament メソッドを呼び出せば、“[” の表示に続いて、(DisplayOrnament のスーパークラスである Display の display メソッドが呼び出され、displayImplement に保存されているインスタンス、すなわち)DisplayUppercase のdisplay メソッドが呼び出され、文字列が大文字で表示されます。そして、“]” の表示がされます。 このように、機能を拡張するためのクラス階層と、実装を拡張するためのクラス階層を分けておくことで、実装階層クラスと機能拡張クラスを好みの組み合わせで利用することができるようになります。今回の例では、 IDisplay インタフェースと Display クラスが機能拡張クラス階層と実装拡張クラス階層を橋渡しする役目を果たしています。 |
共通クラス
|
Bridgeパターンを使用しない例 AbstractDisplayOrnament.scala abstract class AbstractDisplayOrnament extends IDisplay {
def displayOrnament(str: String) {
System.out.print("[")
display(str)
System.out.print("]")
}
}
DisplayOrnamentLowercase.scala class DisplayOrnamentLowercase extends AbstractDisplayOrnament() {
override def display(str: String) {
System.out.print(str.toLowerCase())
}
}
DisplayOrnamentUppercase.scala class DisplayOrnamentUppercase extends AbstractDisplayOrnament() {
override def display(str: String) {
System.out.print(str.toUpperCase())
}
}
Main.scala object Main {
def main(args: Array[String]) {
val dispU = new DisplayUppercase()
dispU.display("AbCdEfGh"); System.out.println()
val dispL = new DisplayLowercase()
dispL.display("AbCdEfGh"); System.out.println()
val dispOU = new DisplayOrnamentUppercase()
dispOU.display("AbCdEfGh"); System.out.println()
dispOU.displayOrnament("AbCdEfGh"); System.out.println()
}
}
|
Bridgeパターンを使用した例 DisplayNormal.scala class DisplayNormal(val dispImp: IDisplay) {
def display(str: String) {
dispImp.display(str)
}
}
DisplayOrnament.scala class DisplayOrnament(val dispImp: IDisplay) extends DisplayNormal(dispImp) {
def displayOrnament(str: String) {
System.out.print("[")
display(str)
System.out.print("]")
}
}
Main.scala object Main {
def main(args: Array[String]) {
val dispU = new DisplayNormal(DisplayUppercase())
dispU.display("AbCdEfGh"); System.out.println()
val dispL = new DisplayNormal(DisplayLowercase())
dispL.display("AbCdEfGh"); System.out.println()
val dispOU = new DisplayOrnament(DisplayUppercase())
dispOU.display("AbCdEfGh"); System.out.println()
dispOU.displayOrnament("AbCdEfGh"); System.out.println()
}
}
|
|
大文字で表示する DisplayUppercase、小文字で表示する DisplayLowercase があるにもかかわらず、[] で囲む DisplayOrnamentUppercase や DisplayOrnamentLowercase の中にも大文字や小文字にする機能を作らなければなりません。 よって、(大文字小文字の2種類)×(修飾有り無しの2種類)分のクラスが必要になります。 |
Bridge パターンでは、実装の変更が考えられるメソッドに関しては、実装用のクラス階層に委譲するように設計します。実装用のクラス階層とは、ここでは display メソッドの実装を与えるクラス階層として、IDisplay インタフェースをインプリメントするクラス階層を考えます。具体的には、Display クラス、 IDisplay インタフェースをコーディング例のようにしておきます。 Display クラスは、コンストラクタで、引数とした渡された、大文字や小文字で表示するクラスのインスタンスをdisplayImplement に保存し、display メソッドで、そのインスタンスのdisplayメソッドを呼び出します。そして、[ ] で囲むクラスのスーパークラスとなります。 IDisplay は、大文字や小文字で表示するクラスに共通するインタフェースとなります。 そして、実際に大文字や小文字に変換する機能を実装する DisplayUppercase クラスと DisplayLowercase クラスを IDisplay インタフェースをインプリメントしたクラスとして作成するようにします。 このような設計にしておくと、機能を追加するために、 Display クラスを継承して作成した新しいクラスでも、すでに存在する実装部分を利用することができるようになります。例えば、 Display クラスを継承して、[]で囲んで表示できるようにした DisplayOrnament クラスです。すでに存在している、大文字や小文字で表示する機能を利用できるのです。 例えば、DisplayUppercase のインスタンスを引数に DisplayOrnament のインスタンスを生成します(displayImplement に DisplayUppercase のインスタンスが保存されます)。そして、そのインスタンスの displayOrnament メソッドを呼び出せば、“[” の表示に続いて、(DisplayOrnament のスーパークラスである Display の display メソッドが呼び出され、displayImplement に保存されているインスタンス、すなわち)DisplayUppercase のdisplay メソッドが呼び出され、文字列が大文字で表示されます。そして、“]” の表示がされます。 このように、機能を拡張するためのクラス階層と、実装を拡張するためのクラス階層を分けておくことで、実装階層クラスと機能拡張クラスを好みの組み合わせで利用することができるようになります。今回の例では、 IDisplay インタフェースと Display クラスが機能拡張クラス階層と実装拡張クラス階層を橋渡しする役目を果たしています。 |
共通クラス
|
Bridgeパターンを使用しない例 AbstractDisplayOrnament.groovy abstract class AbstractDisplayOrnament implements IDisplay {
void displayOrnament(String str) {
System.out.print("[")
display(str)
System.out.print("]")
}
}
DisplayOrnamentLowercase.groovy class DisplayOrnamentLowercase extends AbstractDisplayOrnament {
void display(String str) {
System.out.print(str.toLowerCase())
}
}
DisplayOrnamentUppercase.groovy class DisplayOrnamentUppercase extends AbstractDisplayOrnament {
void display(String str) {
System.out.print(str.toUpperCase())
}
}
Main.groovy public class Main {
static void main(String[] args) {
IDisplay dispU = new DisplayUppercase()
dispU.display("AbCdEfGh"); System.out.println()
IDisplay dispL = new DisplayLowercase()
dispL.display("AbCdEfGh"); System.out.println()
AbstractDisplayOrnament dispOU = new DisplayOrnamentUppercase()
dispOU.display("AbCdEfGh"); System.out.println()
dispOU.displayOrnament("AbCdEfGh"); System.out.println()
}
}
|
Bridgeパターンを使用した例 DisplayNormal.groovy class DisplayNormal {
private IDisplay displayImplement
DisplayNormal(IDisplay dispImp) {
this.displayImplement = dispImp
}
void display(String str) {
displayImplement.display(str)
}
}
DisplayOrnament.groovy class DisplayOrnament extends DisplayNormal {
DisplayOrnament(IDisplay dispImp) {
super(dispImp)
}
void displayOrnament(String str) {
System.out.print("[")
display(str)
System.out.print("]")
}
}
Main.groovy class Main {
static void main(String[] args) {
DisplayNormal dispU = new DisplayNormal(new DisplayUppercase())
dispU.display("AbCdEfGh"); System.out.println()
DisplayNormal dispL = new DisplayNormal(new DisplayLowercase())
dispL.display("AbCdEfGh"); System.out.println()
DisplayOrnament dispOU = new DisplayOrnament(new DisplayUppercase())
dispOU.display("AbCdEfGh"); System.out.println()
dispOU.displayOrnament("AbCdEfGh"); System.out.println()
}
}
|
|
大文字で表示する DisplayUppercase、小文字で表示する DisplayLowercase があるにもかかわらず、[] で囲む DisplayOrnamentUppercase や DisplayOrnamentLowercase の中にも大文字や小文字にする機能を作らなければなりません。 よって、(大文字小文字の2種類)×(修飾有り無しの2種類)分のクラスが必要になります。 |
Bridge パターンでは、実装の変更が考えられるメソッドに関しては、実装用のクラス階層に委譲するように設計します。実装用のクラス階層とは、ここでは display メソッドの実装を与えるクラス階層として、IDisplay インタフェースをインプリメントするクラス階層を考えます。具体的には、Display クラス、 IDisplay インタフェースをコーディング例のようにしておきます。 Display クラスは、コンストラクタで、引数とした渡された、大文字や小文字で表示するクラスのインスタンスをdisplayImplement に保存し、display メソッドで、そのインスタンスのdisplayメソッドを呼び出します。そして、[ ] で囲むクラスのスーパークラスとなります。 IDisplay は、大文字や小文字で表示するクラスに共通するインタフェースとなります。 そして、実際に大文字や小文字に変換する機能を実装する DisplayUppercase クラスと DisplayLowercase クラスを IDisplay インタフェースをインプリメントしたクラスとして作成するようにします。 このような設計にしておくと、機能を追加するために、 Display クラスを継承して作成した新しいクラスでも、すでに存在する実装部分を利用することができるようになります。例えば、 Display クラスを継承して、[]で囲んで表示できるようにした DisplayOrnament クラスです。すでに存在している、大文字や小文字で表示する機能を利用できるのです。 例えば、DisplayUppercase のインスタンスを引数に DisplayOrnament のインスタンスを生成します(displayImplement に DisplayUppercase のインスタンスが保存されます)。そして、そのインスタンスの displayOrnament メソッドを呼び出せば、“[” の表示に続いて、(DisplayOrnament のスーパークラスである Display の display メソッドが呼び出され、displayImplement に保存されているインスタンス、すなわち)DisplayUppercase のdisplay メソッドが呼び出され、文字列が大文字で表示されます。そして、“]” の表示がされます。 このように、機能を拡張するためのクラス階層と、実装を拡張するためのクラス階層を分けておくことで、実装階層クラスと機能拡張クラスを好みの組み合わせで利用することができるようになります。今回の例では、 IDisplay インタフェースと Display クラスが機能拡張クラス階層と実装拡張クラス階層を橋渡しする役目を果たしています。 |
共通クラス
|
Bridgeパターンを使用しない例 AbstractDisplayOrnament.go import "fmt"
type IDisplayOrnament interface {
IDisplay
DisplayOrnament(IDisplayOrnament, string)
}
type AbstractDisplayOrnament struct {
IDisplayOrnament
}
func (self *AbstractDisplayOrnament) DisplayOrnament(display IDisplayOrnament, str string) {
fmt.Print("[")
display.Display(str)
fmt.Print("]")
}
DisplayOrnamentLowercase.go import (
"fmt"
"strings"
)
type DisplayOrnamentLowercase struct {
*AbstractDisplayOrnament
}
func (self *DisplayOrnamentLowercase) Display(str string) {
fmt.Print(strings.ToLower(str))
}
func NewDisplayOrnamentLowercase() *DisplayOrnamentLowercase {
return &DisplayOrnamentLowercase {
AbstractDisplayOrnament: new(AbstractDisplayOrnament),
}
}
DisplayOrnamentUppercase.go import (
"fmt"
"strings"
)
type DisplayOrnamentUppercase struct {
*AbstractDisplayOrnament
}
func (self *DisplayOrnamentUppercase) Display(str string) {
fmt.Print(strings.ToUpperCase(str string)
}
func NewDisplayOrnamentUppercase() *DisplayOrnamentUppercase {
return &DisplayOrnamentUppercase {
AbstractDisplayOrnament: new(AbstractDisplayOrnament),
}
}
Main.go import "fmt"
func main() {
var dispU IDisplay = NewDisplayUppercase()
dispU.Display("AbCdEfGh"); fmt.Println()
var IDisplay dispL = NewDisplayLowercase()
dispL.Display("AbCdEfGh"); fmt.Println()
var dispOU IDisplayOrnament = NewDisplayOrnamentUppercase()
dispOU.Display("AbCdEfGh"); fmt.Println()
dispOU.DisplayOrnament(dispOU, "AbCdEfGh"); fmt.Println()
}
|
Bridgeパターンを使用した例 DisplayNormal.go type DisplayNormal struct {
IDisplay
displayImplement IDisplay
}
func (self *DisplayNormal) Display(str string) {
self.displayImplement.Display(str)
}
func NewDisplayNormal(dispImp IDisplay) *DisplayNormal {
return &DisplayNormal {
displayImplement: dispImp,
}
}
DisplayOrnament.go import "fmt"
type IDisplayOrnament interface {
IDisplay
DisplayOrnament(string)
}
type DisplayOrnament struct {
IDisplayOrnament
*DisplayNormal
}
func (self *DisplayOrnament) Display(str string) {
self.DisplayNormal.Display(str)
}
func (self *DisplayOrnament) DisplayOrnament(str string) {
fmt.Print("[")
self.Display(str)
fmt.Print("]")
}
func NewDisplayOrnament(dispImp IDisplay) *DisplayOrnament {
return &DisplayOrnament{
DisplayNormal: NewDisplayNormal(dispImp),
}
}
Main.go func main() {
var dispU IDisplay = NewDisplayNormal(NewDisplayUppercase())
dispU.Display("AbCdEfGh"); fmt.Println()
var dispL IDisplay = NewDisplayNormal(NewDisplayLowercase())
dispL.Display("AbCdEfGh"); fmt.Println()
var dispOU IDisplayOrnament = NewDisplayOrnament(NewDisplayUppercase())
dispOU.Display("AbCdEfGh"); fmt.Println()
dispOU.DisplayOrnament("AbCdEfGh"); fmt.Println()
}
|
|
大文字で表示する DisplayUppercase、小文字で表示する DisplayLowercase があるにもかかわらず、[] で囲む DisplayOrnamentUppercase や DisplayOrnamentLowercase の中にも大文字や小文字にする機能を作らなければなりません。 よって、(大文字小文字の2種類)×(修飾有り無しの2種類)分のクラスが必要になります。 |
Bridge パターンでは、実装の変更が考えられるメソッドに関しては、実装用のクラス階層に委譲するように設計します。実装用のクラス階層とは、ここでは display メソッドの実装を与えるクラス階層として、IDisplay インタフェースをインプリメントするクラス階層を考えます。具体的には、Display クラス、 IDisplay インタフェースをコーディング例のようにしておきます。 Display クラスは、コンストラクタで、引数とした渡された、大文字や小文字で表示するクラスのインスタンスをdisplayImplement に保存し、display メソッドで、そのインスタンスのdisplayメソッドを呼び出します。そして、[ ] で囲むクラスのスーパークラスとなります。 IDisplay は、大文字や小文字で表示するクラスに共通するインタフェースとなります。 そして、実際に大文字や小文字に変換する機能を実装する DisplayUppercase クラスと DisplayLowercase クラスを IDisplay インタフェースをインプリメントしたクラスとして作成するようにします。 このような設計にしておくと、機能を追加するために、 Display クラスを継承して作成した新しいクラスでも、すでに存在する実装部分を利用することができるようになります。例えば、 Display クラスを継承して、[]で囲んで表示できるようにした DisplayOrnament クラスです。すでに存在している、大文字や小文字で表示する機能を利用できるのです。 例えば、DisplayUppercase のインスタンスを引数に DisplayOrnament のインスタンスを生成します(displayImplement に DisplayUppercase のインスタンスが保存されます)。そして、そのインスタンスの displayOrnament メソッドを呼び出せば、“[” の表示に続いて、(DisplayOrnament のスーパークラスである Display の display メソッドが呼び出され、displayImplement に保存されているインスタンス、すなわち)DisplayUppercase のdisplay メソッドが呼び出され、文字列が大文字で表示されます。そして、“]” の表示がされます。 このように、機能を拡張するためのクラス階層と、実装を拡張するためのクラス階層を分けておくことで、実装階層クラスと機能拡張クラスを好みの組み合わせで利用することができるようになります。今回の例では、 IDisplay インタフェースと Display クラスが機能拡張クラス階層と実装拡張クラス階層を橋渡しする役目を果たしています。 |
共通クラス
|
Bridgeパターンを使用しない例 abstractdisplayornament.d import std.stdio;
import std.string;
import idisplay;
public abstract class AbstractDisplayOrnament : IDisplay {
public void displayOrnament(in string str) {
write("[");
display(str);
write("]");
}
}
displayornamentlowercase.d import std.stdio;
import std.string;
import abstractdisplayornament;
public class DisplayOrnamentLowercase : AbstractDisplayOrnament {
public void display(in string str) {
write(toLower(str));
}
}
displayornamentuppercase.d public class DisplayOrnamentUppercase : AbstractDisplayOrnament {
public void display(in string str) {
write(toUpper(str));
}
}
main.d import std.stdio;
import idisplay;
import displayuppercase;
import displaylowercase;
import displayornamentuppercase;
import abstractdisplayornament;
public int main() {
IDisplay dispU = new DisplayUppercase();
dispU.display("AbCdEfGh"); writeln();
IDisplay dispL = new DisplayLowercase();
dispL.display("AbCdEfGh"); writeln();
AbstractDisplayOrnament dispOU = new DisplayOrnamentUppercase();
dispOU.display("AbCdEfGh"); writeln();
dispOU.displayOrnament("AbCdEfGh"); writeln();
return 0;
}
|
Bridgeパターンを使用した例 displaynormal.d import idisplay;
public class DisplayNormal {
private IDisplay displayImplement;
public this(IDisplay dispImp) {
this.displayImplement = dispImp;
}
public void display(in string str) {
displayImplement.display(str);
}
}
displayornament.d import std.stdio;
import displaynormal;
import idisplay;
public class DisplayOrnament : DisplayNormal {
public this(IDisplay dispImp) {
super(dispImp);
}
public void displayOrnament(in string str) {
write("[");
display(str);
write("]");
}
}
main.d import std.stdio;
import displaynormal;
import displayuppercase;
import displaylowercase;
import displayornament;
public int main() {
DisplayNormal dispU = new DisplayNormal(new DisplayUppercase());
dispU.display("AbCdEfGh"); writeln();
DisplayNormal dispL = new DisplayNormal(new DisplayLowercase());
dispL.display("AbCdEfGh"); writeln();
DisplayOrnament dispOU = new DisplayOrnament(new DisplayUppercase());
dispOU.display("AbCdEfGh"); writeln();
dispOU.displayOrnament("AbCdEfGh"); writeln();
return 0;
}
|
|
大文字で表示する DisplayUppercase、小文字で表示する DisplayLowercase があるにもかかわらず、[] で囲む DisplayOrnamentUppercase や DisplayOrnamentLowercase の中にも大文字や小文字にする機能を作らなければなりません。 よって、(大文字小文字の2種類)×(修飾有り無しの2種類)分のクラスが必要になります。 |
Bridge パターンでは、実装の変更が考えられるメソッドに関しては、実装用のクラス階層に委譲するように設計します。実装用のクラス階層とは、ここでは display メソッドの実装を与えるクラス階層として、IDisplay インタフェースをインプリメントするクラス階層を考えます。具体的には、Display クラス、 IDisplay インタフェースをコーディング例のようにしておきます。 Display クラスは、コンストラクタで、引数とした渡された、大文字や小文字で表示するクラスのインスタンスをdisplayImplement に保存し、display メソッドで、そのインスタンスのdisplayメソッドを呼び出します。そして、[ ] で囲むクラスのスーパークラスとなります。 IDisplay は、大文字や小文字で表示するクラスに共通するインタフェースとなります。 そして、実際に大文字や小文字に変換する機能を実装する DisplayUppercase クラスと DisplayLowercase クラスを IDisplay インタフェースをインプリメントしたクラスとして作成するようにします。 このような設計にしておくと、機能を追加するために、 Display クラスを継承して作成した新しいクラスでも、すでに存在する実装部分を利用することができるようになります。例えば、 Display クラスを継承して、[]で囲んで表示できるようにした DisplayOrnament クラスです。すでに存在している、大文字や小文字で表示する機能を利用できるのです。 例えば、DisplayUppercase のインスタンスを引数に DisplayOrnament のインスタンスを生成します(displayImplement に DisplayUppercase のインスタンスが保存されます)。そして、そのインスタンスの displayOrnament メソッドを呼び出せば、“[” の表示に続いて、(DisplayOrnament のスーパークラスである Display の display メソッドが呼び出され、displayImplement に保存されているインスタンス、すなわち)DisplayUppercase のdisplay メソッドが呼び出され、文字列が大文字で表示されます。そして、“]” の表示がされます。 このように、機能を拡張するためのクラス階層と、実装を拡張するためのクラス階層を分けておくことで、実装階層クラスと機能拡張クラスを好みの組み合わせで利用することができるようになります。今回の例では、 IDisplay インタフェースと Display クラスが機能拡張クラス階層と実装拡張クラス階層を橋渡しする役目を果たしています。 |
共通クラス
|
Bridgeパターンを使用しない例 AbstractDisplayOrnament.pas unit UnitAbstractDisplayOrnament;
interface
uses
UnitIDisplay;
type
AbstractDisplayOrnament = class(TInterfacedObject, IDisplay)
public
procedure displayOrnament(str:string);
procedure display(str:string); virtual; abstract;
end;
implementation
procedure AbstractDisplayOrnament.displayOrnament(str:string);
begin
Write('[');
display(str);
Write(']');
end;
end.
DisplayOrnamentLowercase.pas unit UnitDisplayOrnamentLowercase;
interface
uses
System.SysUtils,
UnitAbstractDisplayOrnament;
type
DisplayOrnamentLowercase = class(AbstractDisplayOrnament)
public
procedure display(str:string); override;
end;
implementation
procedure DisplayOrnamentLowercase.display(str:string);
begin
Write(LowerCase(str));
end;
end.
DisplayOrnamentUppercase.pas unit UnitDisplayOrnamentUppercase;
interface
uses
System.SysUtils,
UnitAbstractDisplayOrnament;
type
DisplayOrnamentLowercase = class(AbstractDisplayOrnament)
public
procedure display(str:string); override;
end;
implementation
procedure DisplayOrnamentLowercase.display(str:string);
begin
Write(UpperCase(str));
end;
end.
Main.dpr program BridgeNon;
uses
System.SysUtils,
UnitIDisplay,
UnitDisplayLowercase,
UnitDisplayUppercase,
UnitAbstractDisplayOrnament,
UnitDisplayOrnamentUppercase;
var dispU:IDisplay;
var dispL:IDisplay;
var dispOU:AbstractDisplayOrnament;
begin
dispU := DisplayUppercase.Create();
dispU.display('AbCdEfGh'); writeln('');
dispL := DisplayLowercase.Create();
dispL.display('AbCdEfGh'); writeln('');
dispOU := DisplayOrnamentUppercase.Create();
dispOU.display('AbCdEfGh'); writeln('');
dispOU.displayOrnament('AbCdEfGh'); writeln('');
end.
|
Bridgeパターンを使用した例 DisplayNormal.pas unit UnitDisplayNormal;
interface
uses
UnitIDisplay;
type
DisplayNormal = class
private
var displayImplement:IDisplay;
public
constructor Create(dispImp:IDisplay);
procedure display(str:string);
end;
implementation
constructor DisplayNormal.Create(dispImp:IDisplay);
begin
displayImplement := dispImp;
end;
procedure DisplayNormal.display(str:string);
begin
displayImplement.display(str);
end;
end.
DisplayOrnament.pas unit UnitDisplayOrnament;
interface
uses
UnitDisplayNormal,
UnitIDisplay;
type
DisplayOrnament = class(DisplayNormal)
public
constructor Create(dispImp:IDisplay);
procedure displayOrnament(str:string);
end;
implementation
constructor DisplayOrnament.Create(dispImp:IDisplay);
begin
inherited Create(dispImp);
end;
procedure DisplayOrnament.displayOrnament(str:string);
begin
Write('[');
display(str);
Write(']');
end;
end.
Main.dpr program Main;
uses
System.SysUtils,
UnitDisplayNormal,
UnitDisplayOrnament,
UnitDisplayLowercase,
UnitDisplayUppercase;
var dispU:DisplayNormal;
var dispL:DisplayNormal;
var dispOU:DisplayOrnament;
begin
dispU := DisplayNormal.Create(DisplayUppercase.Create());
dispU.display('AbCdEfGh'); writeln('');
dispU.Free;
dispL := DisplayNormal.Create(DisplayLowercase.Create());
dispL.display('AbCdEfGh'); writeln('');
dispL.Free;
dispOU := DisplayOrnament.Create(DisplayUppercase.Create());
dispOU.display('AbCdEfGh'); writeln('');
dispOU.displayOrnament('AbCdEfGh'); writeln('');
dispOU.Free;
end.
|
|
大文字で表示する DisplayUppercase、小文字で表示する DisplayLowercase があるにもかかわらず、[] で囲む DisplayOrnamentUppercase や DisplayOrnamentLowercase の中にも大文字や小文字にする機能を作らなければなりません。 よって、(大文字小文字の2種類)×(修飾有り無しの2種類)分のクラスが必要になります。 |
Bridge パターンでは、実装の変更が考えられるメソッドに関しては、実装用のクラス階層に委譲するように設計します。実装用のクラス階層とは、ここでは display メソッドの実装を与えるクラス階層として、IDisplay インタフェースをインプリメントするクラス階層を考えます。具体的には、Display クラス、 IDisplay インタフェースをコーディング例のようにしておきます。 Display クラスは、コンストラクタで、引数とした渡された、大文字や小文字で表示するクラスのインスタンスをdisplayImplement に保存し、display メソッドで、そのインスタンスのdisplayメソッドを呼び出します。そして、[ ] で囲むクラスのスーパークラスとなります。 IDisplay は、大文字や小文字で表示するクラスに共通するインタフェースとなります。 そして、実際に大文字や小文字に変換する機能を実装する DisplayUppercase クラスと DisplayLowercase クラスを IDisplay インタフェースをインプリメントしたクラスとして作成するようにします。 このような設計にしておくと、機能を追加するために、 Display クラスを継承して作成した新しいクラスでも、すでに存在する実装部分を利用することができるようになります。例えば、 Display クラスを継承して、[]で囲んで表示できるようにした DisplayOrnament クラスです。すでに存在している、大文字や小文字で表示する機能を利用できるのです。 例えば、DisplayUppercase のインスタンスを引数に DisplayOrnament のインスタンスを生成します(displayImplement に DisplayUppercase のインスタンスが保存されます)。そして、そのインスタンスの displayOrnament メソッドを呼び出せば、“[” の表示に続いて、(DisplayOrnament のスーパークラスである Display の display メソッドが呼び出され、displayImplement に保存されているインスタンス、すなわち)DisplayUppercase のdisplay メソッドが呼び出され、文字列が大文字で表示されます。そして、“]” の表示がされます。 このように、機能を拡張するためのクラス階層と、実装を拡張するためのクラス階層を分けておくことで、実装階層クラスと機能拡張クラスを好みの組み合わせで利用することができるようになります。今回の例では、 IDisplay インタフェースと Display クラスが機能拡張クラス階層と実装拡張クラス階層を橋渡しする役目を果たしています。 |