Bridge
Bridge – (de)motivační příklad // Helps in providing truly decoupled architecture public interface IBridge { void Function1(); void Function2(); } public class Bridge1 : IBridge public void Function1() Console.WriteLine("Bridge1.Function1"); public void Function2() Console.WriteLine("Bridge1.Function2"); public class Bridge2 : IBridge Console.WriteLine("Bridge2.Function1"); Console.WriteLine("Bridge2.Function2");
Bridge – (de)motivační příklad public interface IAbstractBridge { void CallMethod1(); void CallMethod2(); } public class AbstractBridge : IAbstractBridge public IBridge bridge; public AbstractBridge(IBridge bridge) this.bridge = bridge; public void CallMethod1() this.bridge.Function1(); public void CallMethod2() this.bridge.Function2();
Bridge – názorný příklad
Bridge – názorný příklad
Bridge – názorný příklad
Bridge – názorný příklad
Bridge – názorný příklad
Bridge – názorný příklad
Bridge – názorný příklad
Bridge – přepsaný motivační příklad using System; namespace BridgePattern {// Helps in providing truly decoupled architecture public interface IColor { void PrintLine(int x, int y, int dx, int dy); void PrintPoint(int x, int y); } public class RedColor : IColor { public void PrintLine(int x, int y, int dx, int dy) { Console.BackgroundColor = ConsoleColor.Red; Console.WriteLine("line from ({0},{1}) to ({2},{3})", x, y, dx, dy); public void PrintPoint(int x, int y) { Console.WriteLine("point ({0},{1})", x, y); public class BlueColor : IColor { Console.BackgroundColor = ConsoleColor.Blue;
Bridge – přepsaný motivační příklad public abstract class Shape { protected IColor color; protected Shape(IColor color) this.color = color; } public abstract void Draw();
Bridge – přepsaný motivační příklad public class Circle : Shape { public Circle(IColor color) : base(color) { } public override void Draw() for (int i = 0; i < 2* Math.PI; i++) { int x = (int)Math.Sin(i); int y = (int)Math.Cos(i); color.PrintPoint(x,y); } public class Rectangle : Shape public Rectangle(IColor color) : base(color) { } color.PrintLine(0,0, 0,1); color.PrintLine(0,1, 2,1); color.PrintLine(2,1, 2,0); color.PrintLine(2,0, 0,0);
Bridge – přepsaný motivační příklad class Program { public static void Main(string[] args) Shape s1 = new Rectangle(new RedColor()); Shape s2 = new Circle(new BlueColor()); s1.Draw(); s2.Draw(); Console.ReadKey(true); }
Bridge – výstup příkladu
Bridge – struktura Struktura Účastníci Abstraction RefinedAbstraction typicky obsahuje jen primitivní operace definuje složitější operace pomocí jednodušších z Implementoru Struktura Účastníci Abstraction definuje abstraktní rozhraní objektů, obsahuje odkaz na implementaci s pomocí metod rozhraní Implementor RefinedAbstraction rozšiřuje rozhraní a metody z Abstraction Implementor rozhraní implementací (obecně se liší od Abstraction) ConcreteImplementor konkrétní implementace rozhraní Implementor
Bridge Účel Předpoklady oddělit rozhraní a konkrétní implementace menší počet tříd pro implementaci nezávislý vývoj implementace snadná kompozice znovu-použitelnost implementací Předpoklady danou abstrakci navrhujeme existuje vhodný rozklad do primitivních operací
Bridge – použití Kdy je vhodné použít návrhový vzor Bridge? Nechceme, aby rozhraní a implementace byly pevně svázány možnost výběru nebo přepínání implementace za běhu Chceme: abstrakci a její implementace rozšiřitelné pomoci dědičnosti kombinovat a nezávisle rozšiřovat implementace nemá vliv na klientský kód není nutná rekompilace (stačí znovu pustit linker) skrýt detaily implementace privátní data a metody se píší do hlavičkového souboru (C++) sdílet implementaci mezi více objekty nechceme, aby o tom klient věděl např. reference counting, structural sharing immutable objektů
Bridge – varianty, diskuze Jeden Implementor [PIMPL (Pointer to IMPLementation)] degenerovaný případ účel: skrytí detailů implementace Abstraction má odkaz na třídu Implementor při změně implementace není třeba rekompilovat klientský kód Více Implementorů Implementor se vybere v konstruktoru Abstraction implementaci může vytvářet i Abstract Factory Sdílení Implementorů Implementor je sdílen více objekty více objektů Abstraction má stejný objekt Implementor C++ - reference counting pro zrušení implementace po zrušení posledního odkazu
Bridge – související návrhové vzory Abstract Factory vytváří instance implementací java.awt.Toolkit, java.sql.DriverManager Adapter stejně jako Bridge implementuje rozhraní jedné třídy pomocí metod jiné třídy používá se v případě, že chceme nějakou již existující třídu přizpůsobit požadovanému rozhraní Bridge se používá už v době návrhu tříd Facade pár Abstrakce a Implementor jsou degenerovaný případ Abstrakce může zjednodušovat rozhraní Implementoru
Příklad č. 2
Motivace
Exploze počtu tříd
Rozdělme rozhraní a implementaci Řešení Rozdělme rozhraní a implementaci
Klientská část rozhraní Řešení Klientská část rozhraní
Řešení Abstrakce implementace Klientská část rozhraní
Řešení Abstrakce implementace Klientská část rozhraní Implementováno pomocí abstraktní implementace
Řešení
Bridge – příklad Příklad: multiplatformní systém pro tvorbu GUI rozhraní objektů rozšířené rozhraní odkaz na Implementora class Window { private: WindowImp* imp; public: void DrawContents() = 0; void DrawRect( Point p1, Point p2) { imp = getWindowImp(); imp->Rect(p1.getX(), p1.getY(), p2.getX(), p2.getY()); } protected: WindowImp getWindowImp() { if (imp == nullptr) { imp = WindowFactory.getInstance.makeWindowImp(); return imp; rozhraní pro potomky inicializace na žádost konkrétní implementace class IconWindow : public Window { public: void DrawContents() { WindowImp* imp = getWindowImp(); imp->Bitmap(”icon”, new Coord(0.0), new Coord(0.0)); } delegace
Bridge – příklad Příklad: multiplatformní systém pro tvorbu GUI rozhraní implementací primitivní metody implementace XWindow a WinWindow implementují rozhraní WindowImp konkrétní kreslící funkce mohou obsahovat privátní položky class WindowImp { public: virtual void Rect(Coord c1, Coord c2, Coord c3, Coord c4) = 0; virtual void Text(String string, Coord c1, Coord c2) = 0; virtual void Bitmap(String string, Coord c1, Coord c2) = 0; ... } class XWindowImp : WindowImp { public: virtual void Rect( Coord c1, Coord c2, Coord c3, Coord c4) { ... } ... } class WinWindowImp : WindowImp { public: void Rect( Coord c1, Coord c2, Coord c3, Coord c4) { ... }
Diskuze