「ブリッジ」デザインパターンがまったくわかりません。さまざまなWebサイトを調べましたが、助けにはなりませんでした。
誰でもこれを理解するのに役立つことができますか?
「ブリッジ」デザインパターンがまったくわかりません。さまざまなWebサイトを調べましたが、助けにはなりませんでした。
誰でもこれを理解するのに役立つことができますか?
回答:
OOPではポリモーフィズムを使用するため、抽象化には複数の実装を含めることができます。次の例を見てみましょう。
//trains abstraction
public interface Train
{
move();
}
public class MonoRail:Train
{
public override move()
{
//use one track;
}
}
public class Rail:Train
{
public override move()
{
//use two tracks;
}
}
新しい要件が導入され、列車の加速の観点を取り入れる必要があるため、以下のようにコードを変更します。
public interface Train
{
void move();
}
public class MonoRail:Train
{
public override void move()
{
//use one track;
}
}
public class ElectricMonoRail:MonoRail
{
public override void move()
{
//use electric engine on one track.
}
}
public class DieselMonoRail: MonoRail
{
public override void move()
{
//use diesel engine on one track.
}
}
public class Rail:Train
{
public override void move()
{
//use two tracks;
}
}
public class ElectricRail:Rail
{
public override void move()
{
//use electric engine on two tracks.
}
}
public class DieselRail: Rail
{
public override void move()
{
//use diesel engine on two tracks.
}
}
上記のコードは保守可能ではなく、再利用性に欠けています(同じトラックプラットフォームでアクセラレーションメカニズムを再利用できると仮定した場合)。次のコードは、ブリッジパターンを適用し、2つの異なる抽象化、トレイントランスポートと加速を分離します。
public interface Train
{
void move(Accelerable engine);
}
public interface Accelerable
{
public void accelerate();
}
public class MonoRail:Train
{
public override void move(Accelerable engine)
{
//use one track;
engine.accelerate(); //engine is pluggable (runtime dynamic)
}
}
public class Rail:Train
{
public override void move(Accelerable engine)
{
//use two tracks;
engine.accelerate(); //engine is pluggable (runtime dynamic)
}
}
public class ElectricEngine:Accelerable{/*implementation code for accelerable*/}
public class DieselEngine:Accelerable{/*implementation code for accelerable*/}
Monorail
は実際には2つの単語ではなく、単一の(複合)単語であるためだと思います。MonoRailは、異なる種類のレールではなく、Railのサブクラスになります(これは)。私たちが使用しないことと同じようにSunShine
、またはCupCake
、彼らは次のようになりますSunshine
とCupcake
ほとんどのデザインパターンには役立つ名前がありますが、「ブリッジ」という名前は、その機能に関して直感的ではないことがわかります。
概念的には、クラス階層で使用される実装の詳細を、通常は独自の階層を持つ別のオブジェクトにプッシュします。そうすることで、これらの実装の詳細への密接な依存関係を取り除き、その実装の詳細を変更できるようにします。
小規模では、これを、新しい動作をプラグインできる方法での戦略パターンの使用に例えます。しかし、戦略でよく見られるようにアルゴリズムを単にラップする代わりに、実装オブジェクトは通常、より多くの機能で満たされています。そして、この概念をクラス階層全体に適用すると、大きなパターンがブリッジになります。(繰り返しますが、名前は嫌いです)。
毎日使用するパターンではありませんが、多重継承の(見かけ上の)必要性がある場合に発生する可能性のあるクラスの爆発的な増加を管理する際に役立つことがわかりました。
これが実際の例です。
デザインサーフェイスにコントロールをドロップして構成できるRADツールがあるので、次のようなオブジェクトモデルがあります。
Widget // base class with design surface plumbing
+ Top
+ Left
+ Width
+ Height
+ Name
+ SendToBack
+ BringToFront
+ OnPropertyEdit
+ OnSelect
+ Validate
+ ShowEditor
+ Paint
+ Etc
TextboxWidget : Widget // text box specific
+ Text
+ MaxLength
+ Font
+ ShowEditor // override base to show a property editor form specific to a Textbox
+ Paint // override to render a textbox onto the surface
+ Etc
ListWidget : Widget // list specific
+ Items
+ SelectedItem
+ ShowEditor // override base to show a property editor form specific to a List
+ Paint // override to render a list onto the surface
+ Etc
など、おそらく12個のコントロールがあります。
ただし、その後、複数のテーマ(ルックアンドフィール)をサポートするための新しい要件が追加されます。我々は以下のテーマを持っているとしましょう: Win32
、WinCE
、WinPPC
、WinMo50
、WinMo65
。各テーマには、DefaultFont、DefaultBackColor、BorderWidth、DrawFrame、DrawScrollThumbなどのレンダリング関連の操作のための異なる値または実装があります。
次のようなオブジェクトモデルを作成できます。
Win32TextboxWidget : TextboxWidget
Win32ListWidget : ListWidget
など、1つの制御タイプ用
WinCETextboxWidget : TextboxWidget
WinCEListWidget : ListWidget
など、他のコントロールタイプごと(再度)
アイデアが得られます。ウィジェット数とテーマ数のクラスが爆発的に増えます。これにより、RADデザイナーは、すべてのテーマを認識するようになり、複雑になります。さらに、新しいテーマを追加すると、RADデザイナーが強制的に変更されます。さらに、テーマ内には多くの一般的な実装があり、それを継承することは素晴らしいことですが、コントロールはすでに共通のベース(Widget
)から継承しています。
その代わり、私がやったのは、テーマを実装する別のオブジェクト階層を作成することです。各ウィジェットは、レンダリング操作を実装するオブジェクトへの参照を保持します。多くのテキストでは、このクラスに接尾辞が付いていますImpl
が、その命名規則から外れています。
だから今私のTextboxWidget
ようになります:
TextboxWidget : Widget // text box specific
+ Text
+ MaxLength
+ Font
+ ShowEditor
+ Painter // reference to the implementation of the widget rendering operations
+ Etc
また、さまざまな画家にテーマ固有のベースを継承させることができますが、これは以前はできませんでした。
Win32WidgetPainter
+ DefaultFont
+ DefaultFontSize
+ DefaultColors
+ DrawFrame
+ Etc
Win32TextboxPainter : Win32WidgetPainter
Win32ListPainter : Win32WidgetPainter
良い点の1つは、実行時に実装を動的にロードできることです。これにより、コアソフトウェアを変更せずに、必要な数のテーマを追加できます。言い換えれば、「実装は抽象化とは無関係に変化する可能性があります」。
Win32TextboxPainter
Win32ListPainter
Win32WidgetPainter
StaticStyleControlPainter
EditStyleControlPainter
ButtonStyleControlPainter
ブリッジは、具体的な実装から抽象化を分離することを意図しているため、両方が独立して変化する可能性があります。
ブリッジは構成を使用してこれを実現します。
頻繁な混乱に関する追加の発言
このパターンは、アダプターパターンに非常に似ています。抽象化は、実装に異なるインターフェイスを提供し、そのために構成を使用します。しかし:
これらのパターンの主な違いは、その意図にあります-Gamma
&al、「デザインパターン、再利用可能なオブジェクト指向ソフトウェアの要素」、1995
このデザインパターンに関する優れた独創的な本では、著者も次のことを観察しています。