Міст (англ. Bridge) — шаблон проєктування, призначений для того, щоб відділити абстракцію від її конкретної імплементації таким чином, щоб вони могли бути змінені незалежно один від одного. Належить до класу структурних шаблонів.
Призначення
Відокремити абстракцію від її реалізації таким чином, щоб перше та друге можна було змінювати незалежно одне від одного.
Терміни абстракція та реалізацію не мають нічого спільного з абстрактним класом чи інтерфейсом мови програмування. Абстракція — це уявний рівень керування чим-небудь, що не виконує роботу самостійно, а делегує її рівню реалізації.
Мотивація
Якщо для деякої абстракції можливо кілька реалізацій, зазвичай застосовують наслідування. Абстрактний клас визначає інтерфейс абстракції, а його конкретні підкласи по-різному реалізують його. Але такий підхід не завжди є достатньо гнучким. Наслідування жорстко прив'язує реалізацію до абстракції, що перешкоджає незалежній модифікації, розширенню та повторному використанню абстракції та її реалізації.
Застосовність
Слід використовувати шаблон Міст у випадках, коли:
- треба запобігти постійній прив'язці абстракції до реалізації. Так, наприклад, буває коли реалізацію необхідно обрати під час виконання програми;
- як абстракції, так і реалізації повинні розширюватись новими підкласами. У цьому разі шаблон Міст дозволяє комбінувати різні абстракції та реалізації та змінювати їх незалежно одне від одного;
- зміни у реалізації не повинні впливати на клієнтів, тобто клієнтський код не повинен перекомпілюватись;
- треба повністю сховати від клієнтів реалізацію абстракції;
- треба розподілити одну реалізацію поміж кількох об'єктів (можливо застосовуючи підрахунок посилань), і при цьому приховати це від клієнта.
Структура
- Abstraction — абстракція:
- визначає інтерфейс абстракції;
- зберігає посилання на об'єкт типу Implementor;
- RefinedAbstraction — уточнена абстракція:
- розширює інтерфейс, означений абстракцією Abstraction;
- Implementor — реалізатор:
- визначає інтерфейс для класів реалізації. Він не зобов'язаний точно відповідати інтерфейсу класу Abstraction. Насправді обидва інтерфейси можуть бути зовсім різними. Зазвичай, інтерфейс класу Implementor надає тільки примітивні операції, а клас Abstraction визначає операції більш високого рівня, що базуються на цих примітивах;
- ConcreteImplementor — конкретний реалізатор:
- містить конкретну реалізацію інтерфейсу класу Implementor.
Коли існує тільки одна реалізація, то в цей шаблон називається Pimpl.
Переваги та недоліки
Переваги
- Від'єднання абстракції від реалізації
- Зменшення кількості підкласів
- Чистий код і зменшенням розміру виконуваного файлу
- Інтерфейс і реалізація можуть варіюватися самостійно
- Покращена розширюваність - абстракції та впровадження можуть бути розширені самостійно
Недоліки
- Підвищує складність.
- Подвійна спрямованість - це матиме невеликий вплив на продуктивність.
Відносини
Об'єкт Abstraction містить у собі Implementor і перенаправляє йому запити клієнта.
Зв'язок з іншими патернами
- Міст — це структурний патерн. Його компоненти зазвичай встановлюються раз і не змінюються під час виконання програми. Використовують для розділення абстракції та реалізації. Стратегія — це шаблон поведінки. Використовують коли алгоритми можуть замінювати один одного під час виконання програми.
Реалізація
C++
#include <iostream> using namespace std; // ієрархія реалізації struct IWallCreator { virtual void BuildWall() = 0; virtual void BuildWallWithDoor() = 0; virtual void BuildWallWithWindow() = 0; }; // конкретні реалізації struct BrickWallCreator :public IWallCreator { virtual void BuildWall(){ cout << "Brick & mortar wall.\n"; } virtual void BuildWallWithDoor(){ cout << "Brick & mortar wall with door hole.\n"; } virtual void BuildWallWithWindow(){ cout << "Brick & mortar wall with window hole.\n";} }; struct FoamblockWallCreator :public IWallCreator { virtual void BuildWall() { cout << "Foam wall.\n"; } virtual void BuildWallWithDoor() { cout << "Foam wall.\n"; } virtual void BuildWallWithWindow() { cout << "Foam wall.\n"; } }; // базовий клас абстракції class IBuildCompany { protected: IWallCreator* wallCreator; // міст public: void setWallCreator(IWallCreator* creator) { wallCreator = creator; } virtual void BuildFoundation() = 0; virtual void BuildRoom() = 0; virtual void BuildRoof() = 0; }; // конкретні абстракції struct TownBuildCompany :public IBuildCompany { virtual void BuildFoundation(){cout << "Concrete solid foundation is finished.\n"; } // визначення методів абстракції через методи реалізацї virtual void BuildRoom() { wallCreator->BuildWallWithWindow(); wallCreator->BuildWall(); wallCreator->BuildWall(); wallCreator->BuildWallWithDoor(); cout << "Room is finished.\n"; } virtual void BuildRoof() { cout << "Flat roof is finished.\n";} }; struct CoountryBuildCompany :public IBuildCompany { virtual void BuildFoundation() { cout << "Country foundation is finished.\n"; } virtual void BuildRoom() { wallCreator->BuildWallWithDoor(); wallCreator->BuildWallWithWindow(); wallCreator->BuildWallWithWindow(); wallCreator->BuildWall(); cout << "Room is finished.\n"; } virtual void BuildRoof() { cout << "Roof is finished.\n"; } }; void main() { BrickWallCreator brigade; FoamblockWallCreator team; TownBuildCompany Avalon; CoountryBuildCompany Riel; cout << "*Avalon* has started the building!\n\n"; Avalon.BuildFoundation(); Avalon.setWallCreator(&team); Avalon.BuildRoom(); Avalon.BuildRoom(); cout << " the creator of walls was changed\n"; Avalon.setWallCreator(&brigade); Avalon.BuildRoom(); Avalon.BuildRoof(); cout << "\n*Riel* has started the building!\n\n"; Riel.BuildFoundation(); Riel.setWallCreator(&brigade); Riel.BuildRoom(); Riel.BuildRoom(); Riel.BuildRoof(); }
C#
namespace Bridge { // нехай необхідно реалізувати сховище даних для покупця (Buyer) та замовника (Client), // при чому сховища можуть використовувати як базу даних так і файлову систему // наївна реалізація передбачає створення класу під кожний функціонал // із появою у системі нового типу користувачів чи нового способу збереження // нам доведеться додавати велику кількість класів у ієрархію abstract class StorageBase { . . . } class BuyerDataBaseStorage : StorageBase { . . . } class BuyerFileStorage : StorageBase { . . . } class ClientDataBaseStorage : StorageBase { . . . } class ClientFileStorage : StorageBase { . . . } // даний шаблон пропонує розділити незалежну функціональність (тип користсувача та спосіб збереження) на окремі ієрархії класів // абстракція - ієрархія класів, яка делегує завдання іншій ієрархії // реалізація - ієрархія класів, яка відповідальна за виконнання завдання // ієрархія абстракцій // описує типи користувачів abstract class ContainerBase { StorageBase storage; public void SetStorage(StorageBase storage) { this.storage = storage; } public void Add(object entity) { // абстракція делегує роботу реалізації this.storage.Add(entity); } } class BuyerContainer : ContainerBase { . . . } class ClientContainer : ContainerBase { . . . } // ієрархія реалізації // описує способи збереження abstract class StorageBase { public abstract void Add(object entity); } class DataBaseStorage : StorageBase { . . . } class FileStorage : StorageBase { . . . } // якщо раніше кількість класів у ієрархії становила типи клієнтів * способи збереження (A * B) // то тепер — типи клієнтів + способи збереження (A + B) }
Crystal
abstract class DrawingAPI abstract def draw_circle(x : Float64, y : Float64, radius : Float64) end class DrawingAPI1 < DrawingAPI def draw_circle(x : Float, y : Float, radius : Float) "API1.circle at #{x}:#{y} - radius: #{radius}" end end class DrawingAPI2 < DrawingAPI def draw_circle(x : Float64, y : Float64, radius : Float64) "API2.circle at #{x}:#{y} - radius: #{radius}" end end abstract class Shape protected getter drawing_api : DrawingAPI def initialize(@drawing_api) end abstract def draw abstract def resize_by_percentage(percent : Float64) end class CircleShape < Shape getter x : Float64 getter y : Float64 getter radius : Float64 def initialize(@x, @y, @radius, drawing_api : DrawingAPI) super(drawing_api) end def draw @drawing_api.draw_circle(@x, @y, @radius) end def resize_by_percentage(percent : Float64) @radius *= (1 + percent/100) end end class BridgePattern def self.test shapes = [] of Shape shapes << CircleShape.new(1.0, 2.0, 3.0, DrawingAPI1.new) shapes << CircleShape.new(5.0, 7.0, 11.0, DrawingAPI2.new) shapes.each do |shape| shape.resize_by_percentage(2.5) puts shape.draw end end end BridgePattern.test
Результат:
API1.circle at 1.0:2.0 - radius: 3.075 API2.circle at 5.0:7.0 - radius: 11.275
PHP
interface DrawingAPI { function drawCircle($x, $y, $radius); } class DrawingAPI1 implements DrawingAPI { public function drawCircle($x, $y, $radius) { echo "API1.circle at $x:$y radius $radius.\n"; } } class DrawingAPI2 implements DrawingAPI { public function drawCircle($x, $y, $radius) { echo "API2.circle at $x:$y radius $radius.\n"; } } abstract class Shape { protected $drawingAPI; public abstract function draw(); public abstract function resizeByPercentage($pct); protected function __construct(DrawingAPI $drawingAPI) { $this->drawingAPI = $drawingAPI; } } class CircleShape extends Shape { private $x; private $y; private $radius; public function __construct($x, $y, $radius, DrawingAPI $drawingAPI) { parent::__construct($drawingAPI); $this->x = $x; $this->y = $y; $this->radius = $radius; } public function draw() { $this->drawingAPI->drawCircle($this->x, $this->y, $this->radius); } public function resizeByPercentage($pct) { $this->radius *= $pct; } } class Tester { public static function main() { $shapes = array( new CircleShape(1, 3, 7, new DrawingAPI1()), new CircleShape(5, 7, 11, new DrawingAPI2()), ); foreach ($shapes as $shape) { $shape->resizeByPercentage(2.5); $shape->draw(); } } } Tester::main();
Результат:
API1.circle at 1:3 radius 17.5 API2.circle at 5:7 radius 27.5
Scala
trait DrawingAPI { def drawCircle(x: Double, y: Double, radius: Double) } class DrawingAPI1 extends DrawingAPI { def drawCircle(x: Double, y: Double, radius: Double) = println(s"API #1 $x $y $radius") } class DrawingAPI2 extends DrawingAPI { def drawCircle(x: Double, y: Double, radius: Double) = println(s"API #2 $x $y $radius") } abstract class Shape(drawingAPI: DrawingAPI) { def draw() def resizePercentage(pct: Double) } class CircleShape(x: Double, y: Double, var radius: Double, drawingAPI: DrawingAPI) extends Shape(drawingAPI: DrawingAPI) { def draw() = drawingAPI.drawCircle(x, y, radius) def resizePercentage(pct: Double) { radius *= pct } } object BridgePattern { def main(args: Array[String]) { Seq ( new CircleShape(1, 3, 5, new DrawingAPI1), new CircleShape(4, 5, 6, new DrawingAPI2) ) foreach { x => x.resizePercentage(3) x.draw() } } }
Python
""" Приклад шаблону міст. """ from abc import ABCMeta, abstractmethod NOT_IMPLEMENTED = "You should implement this." class DrawingAPI: __metaclass__ = ABCMeta @abstractmethod def draw_circle(self, x, y, radius): raise NotImplementedError(NOT_IMPLEMENTED) class DrawingAPI1(DrawingAPI): def draw_circle(self, x, y, radius): return f"API1.circle at {x}:{y} - radius: {radius}" class DrawingAPI2(DrawingAPI): def draw_circle(self, x, y, radius): return f"API2.circle at {x}:{y} - radius: {radius}" class DrawingAPI3(DrawingAPI): def draw_circle(self, x, y, radius): return f"API3.circle at {x}:{y} - radius: {radius}" class Shape: __metaclass__ = ABCMeta drawing_api = None def __init__(self, drawing_api): self.drawing_api = drawing_api @abstractmethod def draw(self): raise NotImplementedError(NOT_IMPLEMENTED) @abstractmethod def resize_by_percentage(self, percent): raise NotImplementedError(NOT_IMPLEMENTED) class CircleShape(Shape): def __init__(self, x, y, radius, drawing_api): self.x = x self.y = y self.radius = radius super(CircleShape, self).__init__(drawing_api) def draw(self): return self.drawing_api.draw_circle(self.x, self.y, self.radius) def resize_by_percentage(self, percent): self.radius *= 1 + percent / 100 class BridgePattern: @staticmethod def test(): shapes = [ CircleShape(1.0, 2.0, 3.0, DrawingAPI1()), CircleShape(5.0, 7.0, 11.0, DrawingAPI2()), CircleShape(5.0, 4.0, 12.0, DrawingAPI3()), ] for shape in shapes: shape.resize_by_percentage(2.5) print(shape.draw()) BridgePattern.test()
Джерела
- Design Patterns: Elements of Reusable Object-Oriented Software [ 9 листопада 2012 у Wayback Machine.]
Література
Алан Шаллоуей, Джеймс Р. Тротт. Шаблоны проектирования. Новый подход к объектно-ориентированному анализу и проектированию = Design Patterns Explained: A New Perspective on Object-Oriented Design. — М. : «Вильямс», 2002. — 288 с. — .
Вікіпедія, Українська, Україна, книга, книги, бібліотека, стаття, читати, завантажити, безкоштовно, безкоштовно завантажити, mp3, відео, mp4, 3gp, jpg, jpeg, gif, png, малюнок, музика, пісня, фільм, книга, гра, ігри, мобільний, телефон, android, ios, apple, мобільний телефон, samsung, iphone, xiomi, xiaomi, redmi, honor, oppo, nokia, sonya, mi, ПК, web, Інтернет
Mist angl Bridge shablon proyektuvannya priznachenij dlya togo shob viddiliti abstrakciyu vid yiyi konkretnoyi implementaciyi takim chinom shob voni mogli buti zmineni nezalezhno odin vid odnogo Nalezhit do klasu strukturnih shabloniv PriznachennyaVidokremiti abstrakciyu vid yiyi realizaciyi takim chinom shob pershe ta druge mozhna bulo zminyuvati nezalezhno odne vid odnogo Termini abstrakciya ta realizaciyu ne mayut nichogo spilnogo z abstraktnim klasom chi interfejsom movi programuvannya Abstrakciya ce uyavnij riven keruvannya chim nebud sho ne vikonuye robotu samostijno a deleguye yiyi rivnyu realizaciyi MotivaciyaYaksho dlya deyakoyi abstrakciyi mozhlivo kilka realizacij zazvichaj zastosovuyut nasliduvannya Abstraktnij klas viznachaye interfejs abstrakciyi a jogo konkretni pidklasi po riznomu realizuyut jogo Ale takij pidhid ne zavzhdi ye dostatno gnuchkim Nasliduvannya zhorstko priv yazuye realizaciyu do abstrakciyi sho pereshkodzhaye nezalezhnij modifikaciyi rozshirennyu ta povtornomu vikoristannyu abstrakciyi ta yiyi realizaciyi ZastosovnistSlid vikoristovuvati shablon Mist u vipadkah koli treba zapobigti postijnij priv yazci abstrakciyi do realizaciyi Tak napriklad buvaye koli realizaciyu neobhidno obrati pid chas vikonannya programi yak abstrakciyi tak i realizaciyi povinni rozshiryuvatis novimi pidklasami U comu razi shablon Mist dozvolyaye kombinuvati rizni abstrakciyi ta realizaciyi ta zminyuvati yih nezalezhno odne vid odnogo zmini u realizaciyi ne povinni vplivati na kliyentiv tobto kliyentskij kod ne povinen perekompilyuvatis treba povnistyu shovati vid kliyentiv realizaciyu abstrakciyi treba rozpodiliti odnu realizaciyu pomizh kilkoh ob yektiv mozhlivo zastosovuyuchi pidrahunok posilan i pri comu prihovati ce vid kliyenta StrukturaUML diagrama sho opisuye strukturu shablonu proyektuvannya Mist Abstraction abstrakciya viznachaye interfejs abstrakciyi zberigaye posilannya na ob yekt tipu Implementor RefinedAbstraction utochnena abstrakciya rozshiryuye interfejs oznachenij abstrakciyeyu Abstraction Implementor realizator viznachaye interfejs dlya klasiv realizaciyi Vin ne zobov yazanij tochno vidpovidati interfejsu klasu Abstraction Naspravdi obidva interfejsi mozhut buti zovsim riznimi Zazvichaj interfejs klasu Implementor nadaye tilki primitivni operaciyi a klas Abstraction viznachaye operaciyi bilsh visokogo rivnya sho bazuyutsya na cih primitivah ConcreteImplementor konkretnij realizator mistit konkretnu realizaciyu interfejsu klasu Implementor Koli isnuye tilki odna realizaciya to v C cej shablon nazivayetsya Pimpl Perevagi ta nedolikiPerevagi Vid yednannya abstrakciyi vid realizaciyi Zmenshennya kilkosti pidklasiv Chistij kod i zmenshennyam rozmiru vikonuvanogo fajlu Interfejs i realizaciya mozhut variyuvatisya samostijno Pokrashena rozshiryuvanist abstrakciyi ta vprovadzhennya mozhut buti rozshireni samostijno Nedoliki Pidvishuye skladnist Podvijna spryamovanist ce matime nevelikij vpliv na produktivnist VidnosiniOb yekt Abstraction mistit u sobi Implementor i perenapravlyaye jomu zapiti kliyenta Zv yazok z inshimi paternamiMist ce strukturnij patern Jogo komponenti zazvichaj vstanovlyuyutsya raz i ne zminyuyutsya pid chas vikonannya programi Vikoristovuyut dlya rozdilennya abstrakciyi ta realizaciyi Strategiya ce shablon povedinki Vikoristovuyut koli algoritmi mozhut zaminyuvati odin odnogo pid chas vikonannya programi RealizaciyaC Priklad realizaciyi movoyu S include lt iostream gt using namespace std iyerarhiya realizaciyi struct IWallCreator virtual void BuildWall 0 virtual void BuildWallWithDoor 0 virtual void BuildWallWithWindow 0 konkretni realizaciyi struct BrickWallCreator public IWallCreator virtual void BuildWall cout lt lt Brick amp mortar wall n virtual void BuildWallWithDoor cout lt lt Brick amp mortar wall with door hole n virtual void BuildWallWithWindow cout lt lt Brick amp mortar wall with window hole n struct FoamblockWallCreator public IWallCreator virtual void BuildWall cout lt lt Foam wall n virtual void BuildWallWithDoor cout lt lt Foam wall n virtual void BuildWallWithWindow cout lt lt Foam wall n bazovij klas abstrakciyi class IBuildCompany protected IWallCreator wallCreator mist public void setWallCreator IWallCreator creator wallCreator creator virtual void BuildFoundation 0 virtual void BuildRoom 0 virtual void BuildRoof 0 konkretni abstrakciyi struct TownBuildCompany public IBuildCompany virtual void BuildFoundation cout lt lt Concrete solid foundation is finished n viznachennya metodiv abstrakciyi cherez metodi realizacyi virtual void BuildRoom wallCreator gt BuildWallWithWindow wallCreator gt BuildWall wallCreator gt BuildWall wallCreator gt BuildWallWithDoor cout lt lt Room is finished n virtual void BuildRoof cout lt lt Flat roof is finished n struct CoountryBuildCompany public IBuildCompany virtual void BuildFoundation cout lt lt Country foundation is finished n virtual void BuildRoom wallCreator gt BuildWallWithDoor wallCreator gt BuildWallWithWindow wallCreator gt BuildWallWithWindow wallCreator gt BuildWall cout lt lt Room is finished n virtual void BuildRoof cout lt lt Roof is finished n void main BrickWallCreator brigade FoamblockWallCreator team TownBuildCompany Avalon CoountryBuildCompany Riel cout lt lt Avalon has started the building n n Avalon BuildFoundation Avalon setWallCreator amp team Avalon BuildRoom Avalon BuildRoom cout lt lt the creator of walls was changed n Avalon setWallCreator amp brigade Avalon BuildRoom Avalon BuildRoof cout lt lt n Riel has started the building n n Riel BuildFoundation Riel setWallCreator amp brigade Riel BuildRoom Riel BuildRoom Riel BuildRoof C Priklad realizaciyi movoyu S namespace Bridge nehaj neobhidno realizuvati shovishe danih dlya pokupcya Buyer ta zamovnika Client pri chomu shovisha mozhut vikoristovuvati yak bazu danih tak i fajlovu sistemu nayivna realizaciya peredbachaye stvorennya klasu pid kozhnij funkcional iz poyavoyu u sistemi novogo tipu koristuvachiv chi novogo sposobu zberezhennya nam dovedetsya dodavati veliku kilkist klasiv u iyerarhiyu abstract class StorageBase class BuyerDataBaseStorage StorageBase class BuyerFileStorage StorageBase class ClientDataBaseStorage StorageBase class ClientFileStorage StorageBase danij shablon proponuye rozdiliti nezalezhnu funkcionalnist tip koristsuvacha ta sposib zberezhennya na okremi iyerarhiyi klasiv abstrakciya iyerarhiya klasiv yaka deleguye zavdannya inshij iyerarhiyi realizaciya iyerarhiya klasiv yaka vidpovidalna za vikonnannya zavdannya iyerarhiya abstrakcij opisuye tipi koristuvachiv abstract class ContainerBase StorageBase storage public void SetStorage StorageBase storage this storage storage public void Add object entity abstrakciya deleguye robotu realizaciyi this storage Add entity class BuyerContainer ContainerBase class ClientContainer ContainerBase iyerarhiya realizaciyi opisuye sposobi zberezhennya abstract class StorageBase public abstract void Add object entity class DataBaseStorage StorageBase class FileStorage StorageBase yaksho ranishe kilkist klasiv u iyerarhiyi stanovila tipi kliyentiv sposobi zberezhennya A B to teper tipi kliyentiv sposobi zberezhennya A B Crystal Priklad realizaciyi movoyu Crystal abstract class DrawingAPI abstract def draw circle x Float64 y Float64 radius Float64 end class DrawingAPI1 lt DrawingAPI def draw circle x Float y Float radius Float API1 circle at x y radius radius end end class DrawingAPI2 lt DrawingAPI def draw circle x Float64 y Float64 radius Float64 API2 circle at x y radius radius end end abstract class Shape protected getter drawing api DrawingAPI def initialize drawing api end abstract def draw abstract def resize by percentage percent Float64 end class CircleShape lt Shape getter x Float64 getter y Float64 getter radius Float64 def initialize x y radius drawing api DrawingAPI super drawing api end def draw drawing api draw circle x y radius end def resize by percentage percent Float64 radius 1 percent 100 end end class BridgePattern def self test shapes of Shape shapes lt lt CircleShape new 1 0 2 0 3 0 DrawingAPI1 new shapes lt lt CircleShape new 5 0 7 0 11 0 DrawingAPI2 new shapes each do shape shape resize by percentage 2 5 puts shape draw end end end BridgePattern test Rezultat API1 circle at 1 0 2 0 radius 3 075 API2 circle at 5 0 7 0 radius 11 275 PHP Priklad realizaciyi movoyu PHP interface DrawingAPI function drawCircle x y radius class DrawingAPI1 implements DrawingAPI public function drawCircle x y radius echo API1 circle at x y radius radius n class DrawingAPI2 implements DrawingAPI public function drawCircle x y radius echo API2 circle at x y radius radius n abstract class Shape protected drawingAPI public abstract function draw public abstract function resizeByPercentage pct protected function construct DrawingAPI drawingAPI this gt drawingAPI drawingAPI class CircleShape extends Shape private x private y private radius public function construct x y radius DrawingAPI drawingAPI parent construct drawingAPI this gt x x this gt y y this gt radius radius public function draw this gt drawingAPI gt drawCircle this gt x this gt y this gt radius public function resizeByPercentage pct this gt radius pct class Tester public static function main shapes array new CircleShape 1 3 7 new DrawingAPI1 new CircleShape 5 7 11 new DrawingAPI2 foreach shapes as shape shape gt resizeByPercentage 2 5 shape gt draw Tester main Rezultat API1 circle at 1 3 radius 17 5 API2 circle at 5 7 radius 27 5 Scala Priklad realizaciyi movoyu Scala trait DrawingAPI def drawCircle x Double y Double radius Double class DrawingAPI1 extends DrawingAPI def drawCircle x Double y Double radius Double println s API 1 x y radius class DrawingAPI2 extends DrawingAPI def drawCircle x Double y Double radius Double println s API 2 x y radius abstract class Shape drawingAPI DrawingAPI def draw def resizePercentage pct Double class CircleShape x Double y Double var radius Double drawingAPI DrawingAPI extends Shape drawingAPI DrawingAPI def draw drawingAPI drawCircle x y radius def resizePercentage pct Double radius pct object BridgePattern def main args Array String Seq new CircleShape 1 3 5 new DrawingAPI1 new CircleShape 4 5 6 new DrawingAPI2 foreach x gt x resizePercentage 3 x draw Python Priklad realizaciyi movoyu Python Priklad shablonu mist from abc import ABCMeta abstractmethod NOT IMPLEMENTED You should implement this class DrawingAPI metaclass ABCMeta abstractmethod def draw circle self x y radius raise NotImplementedError NOT IMPLEMENTED class DrawingAPI1 DrawingAPI def draw circle self x y radius return f API1 circle at x y radius radius class DrawingAPI2 DrawingAPI def draw circle self x y radius return f API2 circle at x y radius radius class DrawingAPI3 DrawingAPI def draw circle self x y radius return f API3 circle at x y radius radius class Shape metaclass ABCMeta drawing api None def init self drawing api self drawing api drawing api abstractmethod def draw self raise NotImplementedError NOT IMPLEMENTED abstractmethod def resize by percentage self percent raise NotImplementedError NOT IMPLEMENTED class CircleShape Shape def init self x y radius drawing api self x x self y y self radius radius super CircleShape self init drawing api def draw self return self drawing api draw circle self x self y self radius def resize by percentage self percent self radius 1 percent 100 class BridgePattern staticmethod def test shapes CircleShape 1 0 2 0 3 0 DrawingAPI1 CircleShape 5 0 7 0 11 0 DrawingAPI2 CircleShape 5 0 4 0 12 0 DrawingAPI3 for shape in shapes shape resize by percentage 2 5 print shape draw BridgePattern test DzherelaDesign Patterns Elements of Reusable Object Oriented Software 9 listopada 2012 u Wayback Machine LiteraturaAlan Shallouej Dzhejms R Trott Shablony proektirovaniya Novyj podhod k obektno orientirovannomu analizu i proektirovaniyu Design Patterns Explained A New Perspective on Object Oriented Design M Vilyams 2002 288 s ISBN 0 201 71594 5