Most vzor - Bridge pattern
The most vzor je návrhový vzor použito v softwarové inženýrství to je určeno "oddělit abstrakce od jeho implementace aby se ti dva mohli nezávisle měnit “, představený Gang čtyř.[1] The most používá zapouzdření, agregace, a může použít dědictví rozdělit odpovědnosti na různé třídy.
Když se třída často mění, vlastnosti objektově orientované programování se staly velmi užitečnými, protože změny a program je kód lze snadno vytvořit s minimálními předchozími znalostmi o programu. Mostový vzor je užitečný, když se často liší třída i to, co dělá. Samotnou třídu lze považovat za abstrakce a co může třída dělat jako implementace. Mostový vzor lze také považovat za dvě vrstvy abstrakce.
Pokud existuje pouze jedna pevná implementace, je tento vzor znám jako Pimpl idiom v C ++ svět.
Mostový vzor je často zaměňován s vzor adaptéru, a je často implementován pomocí vzor adaptéru objektu; např. v Java kódu níže.
Varianta: Implementaci lze ještě více oddělit odložením přítomnosti implementace do bodu, kdy se využívá abstrakce.
Přehled
Most [2]designový vzor je jedním z dvaceti tří známých GoF návrhové vzory které popisují, jak řešit opakující se konstrukční problémy při navrhování flexibilního a opakovaně použitelného objektově orientovaného softwaru, tj. objektů, které se snadněji implementují, mění, testují a znovu používají.
Jaké problémy může návrhový vzor Bridge vyřešit?[3]
- Abstrakce a její implementace by měly být definovány a rozšiřovány nezávisle na sobě.
- Je třeba se vyhnout vazbě kompilace mezi abstrakcí a její implementací, aby bylo možné vybrat implementaci za běhu.
Při použití podtřídy různé podtřídy implementují abstraktní třídu různými způsoby. Ale implementace je vázána na abstrakci v době kompilace a nelze ji změnit za běhu.
Jaké řešení popisuje návrhový vzor Bridge?
- Oddělte abstrakci (
Abstrakce
) od jeho implementace (Realizátor
) vložením do samostatných třídních hierarchií. - Proveďte
Abstrakce
z hlediska (delegováním na) anRealizátor
objekt.
To umožňuje konfigurovat Abstrakce
s Realizátor
objekt za běhu.
Viz také Unifikovaný Modelovací Jazyk třídní a sekvenční diagram níže.
Struktura
Třída a sekvenční diagram UML

Ve výše uvedeném Unified Modeling Language třídní diagram, abstrakce (Abstrakce
) není implementována jako obvykle v jedné hierarchii dědičnosti. Místo toho existuje jedna hierarchie pro abstrakci (Abstrakce
) a samostatná hierarchie pro jeho implementaci (Realizátor
), díky čemuž jsou dva na sobě nezávislí Abstrakce
rozhraní (úkon()
) je implementován ve smyslu (pověřením) Realizátor
rozhraní (imp.operationImp ()
).
The UML sekvenční diagram ukazuje interakce za běhu: Abstrakce
implementace delegátů objektu do Implementátor1
objekt (voláním operationImp ()
na Implementátor1
), který provede operaci a vrátí se do Abstrakce
.
Diagram tříd
- Abstrakce (abstraktní třída)
- definuje abstraktní rozhraní
- udržuje odkaz na implementátora.
- RefinedAbstraction (normální třída)
- rozšiřuje rozhraní definované Abstrakcí
- Implementátor (rozhraní)
- definuje rozhraní pro implementační třídy
- ConcreteImplementor (normální třída)
- implementuje rozhraní implementátoru
Příklad
C#
Mostový vzor tvoří objekty ve stromové struktuře. Odděluje abstrakci od implementace. Zde abstrakce představuje klienta, ze kterého budou objekty volány. Níže je uveden příklad implementovaný v C #
// Pomáhá při zajišťování skutečně oddělené architekturyveřejnost rozhraní IBridge{ prázdnota Funkce1(); prázdnota Funkce2();}veřejnost třída Bridge1 : IBridge{ veřejnost prázdnota Funkce1() { Řídicí panel.WriteLine(„Bridge1.Function1“); } veřejnost prázdnota Funkce2() { Řídicí panel.WriteLine(„Bridge1.Function2“); }}veřejnost třída Bridge2 : IBridge{ veřejnost prázdnota Funkce1() { Řídicí panel.WriteLine(„Bridge2.Function1“); } veřejnost prázdnota Funkce2() { Řídicí panel.WriteLine(„Bridge2.Function2“); }}veřejnost rozhraní IAbstractBridge{ prázdnota CallMethod1(); prázdnota CallMethod2();}veřejnost třída AbstractBridge : IAbstractBridge{ veřejnost IBridge most; veřejnost Abstraktní most(IBridge most) { tento.most = most; } veřejnost prázdnota CallMethod1() { tento.most.Funkce1(); } veřejnost prázdnota CallMethod2() { tento.most.Funkce2(); }}
Třídy Bridge jsou implementací, která k vytváření objektů používá stejnou architekturu orientovanou na rozhraní. Na druhou stranu abstrakce přebírá instanci implementační třídy a spouští svou metodu. Jsou tedy od sebe zcela odděleny.
Krystal
abstraktní třída DrawingAPI abstraktní def draw_circle(X : Float64, y : Float64, poloměr : Float64)konectřída Kreslení API1 < DrawingAPI def draw_circle(X : Plovák, y : Plovák, poloměr : Plovák) "API1.circle na #{X}:#{y} - poloměr: #{poloměr}" koneckonectřída KresleníAPI2 < DrawingAPI def draw_circle(X : Float64, y : Float64, poloměr : Float64) "API2.circle na #{X}:#{y} - poloměr: #{poloměr}" koneckonecabstraktní třída Tvar chráněný kariérista drawing_api : DrawingAPI def inicializovat(@drawing_api) konec abstraktní def kreslit abstraktní def resize_by_percentage(procent : Float64)konectřída CircleShape < Tvar kariérista X : Float64 kariérista y : Float64 kariérista poloměr : Float64 def inicializovat(@X, @y, @poloměr, drawing_api : DrawingAPI) super(drawing_api) konec def kreslit @drawing_api.draw_circle(@X, @y, @poloměr) konec def resize_by_percentage(procent : Float64) @poloměr *= (1 + procent/100) koneckonectřída MostVzorek def já.test tvary = [] z Tvar tvary << CircleShape.Nový(1.0, 2.0, 3.0, Kreslení API1.Nový) tvary << CircleShape.Nový(5.0, 7.0, 11.0, KresleníAPI2.Nový) tvary.každý dělat |tvar| tvar.resize_by_percentage(2.5) uvádí tvar.kreslit konec koneckonecMostVzorek.test
Výstup
API1.circle at 1.0: 2.0 - radius: 3.075API2.circle at 5.0: 7.0 - radius: 11.275
C ++
#zahrnout <iostream>#zahrnout <string>#zahrnout <vector>třída DrawingAPI { veřejnost: virtuální ~DrawingAPI() = výchozí; virtuální std::tětiva DrawCircle(plovák X, plovák y, plovák poloměr) konst = 0;};třída Kreslení API01 : veřejnost DrawingAPI { veřejnost: std::tětiva DrawCircle(plovák X, plovák y, plovák poloměr) konst přepsat { vrátit se „API01.circle at“ + std::to_string(X) + ":" + std::to_string(y) + "- poloměr:" + std::to_string(poloměr); }};třída Kreslení API02 : veřejnost DrawingAPI { veřejnost: std::tětiva DrawCircle(plovák X, plovák y, plovák poloměr) konst přepsat { vrátit se „API02.circle at“ + std::to_string(X) + ":" + std::to_string(y) + "- poloměr:" + std::to_string(poloměr); }};třída Tvar { veřejnost: Tvar(konst DrawingAPI& drawing_api) : drawing_api_(drawing_api) {} virtuální ~Tvar() = výchozí; virtuální std::tětiva Kreslit() konst = 0; virtuální plovák ResizeByPercentage(konst plovák procent) = 0; chráněný: konst DrawingAPI& drawing_api_;};třída CircleShape: veřejnost Tvar { veřejnost: CircleShape(plovák X, plovák y, plovák poloměr, konst DrawingAPI& drawing_api) : Tvar(drawing_api), X_(X), y_(y), poloměr_(poloměr) {} std::tětiva Kreslit() konst přepsat { vrátit se drawing_api_.DrawCircle(X_, y_, poloměr_); } plovák ResizeByPercentage(konst plovák procent) přepsat { vrátit se poloměr_ *= (1,0f + procent/100,0f); } soukromé: plovák X_, y_, poloměr_;};int hlavní(int argc, char** argv) { std::vektor<CircleShape> tvary { CircleShape{1,0f, 2,0f, 3,0f, Kreslení API01{}}, CircleShape{5,0f, 7,0 f, 11.0f, Kreslení API02{}} }; pro (auto& tvar: tvary) { tvar.ResizeByPercentage(2.5); std::cout << tvar.Kreslit() << std::konec; } vrátit se 0;}
Výstup:
API01.circle at 1.000000: 2.000000 - radius: 3.075000 API02.circle at 5.000000: 7.000000 - radius: 11.275000
Jáva
Následující Jáva program definuje bankovní účet, který odděluje operace účtu od protokolování těchto operací.
// Logger má dvě implementace: informace a varování@Funkčnírozhranírozhraní Logger { prázdnota log(Tětiva zpráva); statický Logger informace() { vrátit se zpráva -> Systém.ven.tisk("informace:" + zpráva); } statický Logger Varování() { vrátit se zpráva -> Systém.ven.tisk("Varování: " + zpráva); }}abstraktní třída Abstraktní účet { soukromé Logger záznamník = Logger.informace(); veřejnost prázdnota setLogger(Logger záznamník) { tento.záznamník = záznamník; } // protokolovací část je delegována na implementaci Logger chráněný prázdnota fungovat(Tětiva zpráva, booleovský výsledek) { záznamník.log(zpráva + " výsledek " + výsledek); }}třída SimpleAccount rozšiřuje Abstraktní účet { soukromé int Zůstatek; veřejnost SimpleAccount(int Zůstatek) { tento.Zůstatek = Zůstatek; } veřejnost booleovský isBalanceLow() { vrátit se Zůstatek < 50; } veřejnost prázdnota ustoupit(int množství) { booleovský shouldPerform = Zůstatek >= množství; -li (shouldPerform) { Zůstatek -= množství; } fungovat("ustoupit " + množství, shouldPerform); }}veřejnost třída BridgeDemo { veřejnost statický prázdnota hlavní(Tětiva[] args) { SimpleAccount účet = Nový SimpleAccount(100); účet.ustoupit(75); -li (účet.isBalanceLow()) { // implementaci Loggeru můžete také změnit za běhu účet.setLogger(Logger.Varování()); } účet.ustoupit(10); účet.ustoupit(100); }}
Bude výstup:
informace: výběr 75 výsledků truewarning: výběr 10 výsledků truewarning: výběr 100 výsledků false
PHP
rozhraní DrawingAPI{ funkce drawCircle($ x, $ r, $ rádius);}třída Kreslení API1 nářadí DrawingAPI{ veřejnost funkce drawCircle($ x, $ r, $ rádius) { echo "API1.circle na $ x:$ r poloměr $ rádius. n"; }}třída KresleníAPI2 nářadí DrawingAPI{ veřejnost funkce drawCircle($ x, $ r, $ rádius) { echo "API2.circle na $ x:$ r poloměr $ rádius. n"; }}abstraktní třída Tvar{ chráněný $ drawingAPI; veřejnost abstraktní funkce kreslit(); veřejnost abstraktní funkce resizeByPercentage($ pct); chráněný funkce __postavit(DrawingAPI $ drawingAPI) { $ toto->kreslení API = $ drawingAPI; }}třída CircleShape rozšiřuje Tvar{ soukromé $ x; soukromé $ r; soukromé $ rádius; veřejnost funkce __postavit($ x, $ r, $ rádius, DrawingAPI $ drawingAPI) { rodič::__postavit($ drawingAPI); $ toto->X = $ x; $ toto->y = $ r; $ toto->poloměr = $ rádius; } veřejnost funkce kreslit() { $ toto->kreslení API->drawCircle($ toto->X, $ toto->y, $ toto->poloměr); } veřejnost funkce resizeByPercentage($ pct) { $ toto->poloměr *= $ pct; }}třída Tester{ veřejnost statický funkce hlavní() { $ tvary = pole( Nový CircleShape(1, 3, 7, Nový Kreslení API1()), Nový CircleShape(5, 7, 11, Nový KresleníAPI2()), ); pro každého ($ tvary tak jako $ tvar) { $ tvar->resizeByPercentage(2.5); $ tvar->kreslit(); } }}Tester::hlavní();
Výstup:
API1.kruh v poloměru 1: 3 17,5 API2.kruh v poloměru 5: 7 27,5
Scala
vlastnost DrawingAPI { def drawCircle(X: Dvojnásobek, y: Dvojnásobek, poloměr: Dvojnásobek)}třída Kreslení API1 rozšiřuje DrawingAPI { def drawCircle(X: Dvojnásobek, y: Dvojnásobek, poloměr: Dvojnásobek) = tisk(s "API č. 1 $ x$ r$ rádius")}třída KresleníAPI2 rozšiřuje DrawingAPI { def drawCircle(X: Dvojnásobek, y: Dvojnásobek, poloměr: Dvojnásobek) = tisk(s "API č. 2 $ x$ r$ rádius")}abstraktní třída Tvar(kreslení API: DrawingAPI) { def kreslit() def resizePercentage(pct: Dvojnásobek)}třída CircleShape(X: Dvojnásobek, y: Dvojnásobek, var poloměr: Dvojnásobek, kreslení API: DrawingAPI) rozšiřuje Tvar(kreslení API: DrawingAPI) { def kreslit() = kreslení API.drawCircle(X, y, poloměr) def resizePercentage(pct: Dvojnásobek) { poloměr *= pct }}objekt MostVzorek { def hlavní(args: Pole[Tětiva]) { Sekv ( Nový CircleShape(1, 3, 5, Nový Kreslení API1), Nový CircleShape(4, 5, 6, Nový KresleníAPI2) ) pro každého { X => X.resizePercentage(3) X.kreslit() } }}
Krajta
"""Příklad mostního vzoru."""z abc import ABCMeta, abstraktní metodaNENÍ IMPLEMENTOVÁNO = „Měli byste to implementovat.“třída DrawingAPI: __metaclass__ = ABCMeta @abstractmethod def draw_circle(já, X, y, poloměr): vyzdvihnout NotImplementedError(NENÍ IMPLEMENTOVÁNO)třída Kreslení API1(DrawingAPI): def draw_circle(já, X, y, poloměr): vrátit se F"API1.circle na {X}:{y} - poloměr: {poloměr}"třída KresleníAPI2(DrawingAPI): def draw_circle(já, X, y, poloměr): vrátit se F"API2.circle na {X}:{y} - poloměr: {poloměr}"třída Kreslení API3(DrawingAPI): def draw_circle(já, X, y, poloměr): vrátit se F"API3.circle na {X}:{y} - poloměr: {poloměr}"třída Tvar: __metaclass__ = ABCMeta drawing_api = Žádný def __init__(já, drawing_api): já.drawing_api = drawing_api @abstractmethod def kreslit(já): vyzdvihnout NotImplementedError(NENÍ IMPLEMENTOVÁNO) @abstractmethod def resize_by_percentage(já, procent): vyzdvihnout NotImplementedError(NENÍ IMPLEMENTOVÁNO)třída CircleShape(Tvar): def __init__(já, X, y, poloměr, drawing_api): já.X = X já.y = y já.poloměr = poloměr super(CircleShape, já).__init__(drawing_api) def kreslit(já): vrátit se já.drawing_api.draw_circle(já.X, já.y, já.poloměr) def resize_by_percentage(já, procent): já.poloměr *= 1 + procent / 100třída MostVzorek: @staticmethod def test(): tvary = [ CircleShape(1.0, 2.0, 3.0, Kreslení API1()), CircleShape(5.0, 7.0, 11.0, KresleníAPI2()), CircleShape(5.0, 4.0, 12.0, Kreslení API3()), ] pro tvar v tvary: tvar.resize_by_percentage(2.5) tisk(tvar.kreslit())MostVzorek.test()
Viz také
Reference
- ^ Gamma, E, Helm, R, Johnson, R, Vlissides, J: Designové vzory, strana 151. Addison-Wesley, 1995
- ^ Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides (1994). Návrhové vzory: Prvky opakovaně použitelného objektově orientovaného softwaru. Addison Wesley. str.151ff. ISBN 0-201-63361-2.CS1 maint: více jmen: seznam autorů (odkaz)
- ^ „Návrhový vzor mostu - problém, řešení a použitelnost“. w3sDesign.com. Citováno 2017-08-12.
- ^ „Návrhový vzor mostu - struktura a spolupráce“. w3sDesign.com. Citováno 2017-08-12.
externí odkazy
- Bridge v UML a v LePUS3 (formální modelovací jazyk)
- C # návrhové vzory: Vzor mostu. Ukázková kapitola. 2002-12-20. Z: James W. Cooper (2003). C # Design Patterns: A Tutorial. Addison-Wesley. ISBN 0-201-84453-2.