Köprü deseni - Bridge pattern

köprü düzeni bir tasarım deseni kullanılan yazılım Mühendisliği bunun anlamı "ayırmak soyutlama ondan uygulama böylece ikisi birbirinden bağımsız olarak değişebilir "tarafından tanıtıldı Dörtlü Çete.[1] köprü kullanır kapsülleme, toplama ve kullanabilir miras sorumlulukları farklı sınıflar.

Bir sınıf sık sık değiştiğinde, özellikleri nesne yönelimli programlama çok kullanışlı hale gelir çünkü bir program 's kodu program hakkında minimum ön bilgi ile kolayca yapılabilir. Köprü modeli, hem sınıf hem de ne yaptığı sık sık değiştiğinde kullanışlıdır. Sınıfın kendisi şu şekilde düşünülebilir: soyutlama ve sınıfın yapabileceği uygulama. Köprü örüntüsü iki soyutlama katmanı olarak da düşünülebilir.

Yalnızca tek bir sabit uygulama olduğunda, bu model Pezevenk deyim C ++ dünya.

Köprü örüntüsü genellikle şunlarla karıştırılır: adaptör kalıbı ve genellikle nesne bağdaştırıcı deseni; ör. aşağıdaki Java kodunda.

Varyasyon: Uygulama, uygulamanın varlığını soyutlamanın kullanıldığı noktaya kadar erteleyerek daha da ayrıştırılabilir.

Genel Bakış

Köprü [2]tasarım deseni, iyi bilinen yirmi üç tanesinden biridir. GoF tasarım modelleri esnek ve yeniden kullanılabilir nesne yönelimli yazılımlar, yani uygulanması, değiştirilmesi, test edilmesi ve yeniden kullanılması daha kolay nesneler tasarlamak için yinelenen tasarım problemlerinin nasıl çözüleceğini açıklar.

Köprü tasarım modeli hangi sorunları çözebilir?[3]

  • Bir soyutlama ve uygulaması birbirinden bağımsız olarak tanımlanmalı ve genişletilmelidir.
  • Çalışma zamanında bir uygulamanın seçilebilmesi için, bir soyutlama ve uygulaması arasındaki derleme zamanı bağlamasından kaçınılmalıdır.

Alt sınıflandırma kullanılırken, farklı alt sınıflar soyut bir sınıfı farklı şekillerde uygular. Ancak bir uygulama, derleme zamanında soyutlamaya bağlıdır ve çalışma zamanında değiştirilemez.

Bridge tasarım modeli hangi çözümü tanımlar?

  • Bir soyutlamayı ayırın (Soyutlama) uygulamasından (Uygulayıcı) ayrı sınıf hiyerarşilerine koyarak.
  • Uygulayın Soyutlama açısından (delege ederek) bir Uygulayıcı nesne.

Bu, bir Soyutlama bir ile Uygulayıcı çalışma zamanında nesne.
Ayrıca bkz. Birleştirilmiş Modelleme Dili aşağıdaki sınıf ve sıra diyagramı.

Yapısı

UML sınıfı ve sıra diyagramı

Köprü tasarım modeli için örnek bir UML sınıfı ve sıra diyagramı. [4]

Yukarıdaki Birleşik Modelleme Dilinde sınıf diyagramı, bir soyutlama (Soyutlama) tek bir kalıtım hiyerarşisinde olağan şekilde uygulanmaz.Bunun yerine, bir soyutlama için bir hiyerarşi vardır (Soyutlama) ve uygulaması için ayrı bir hiyerarşi (Uygulayıcı), bu ikisini birbirinden bağımsız kılar. Soyutlama arayüz (operasyon()) açısından (delege ederek) uygulanır. Uygulayıcı arayüz (imp.operationImp ()).
UML sıra diyagramı çalışma zamanı etkileşimlerini gösterir: Soyutlama1 nesne, uygulamayı Uygulayıcı1 nesne (çağırarak operationImp () açık Uygulayıcı1), işlemi gerçekleştiren ve geri dönen Soyutlama1.

Sınıf diyagramı

Bridge UML sınıfı diagram.svg

Soyutlama (soyut sınıf)
soyut arayüzü tanımlar
Uygulayıcı referansını korur.
RefinedAbstraction (normal sınıf)
Abstraction tarafından tanımlanan arayüzü genişletir
Uygulayıcı (arayüz)
uygulama sınıfları için arayüzü tanımlar
ConcreteImplementor (normal sınıf)
Uygulayıcı arayüzünü uygular
İçinde köprü LePUS3 (efsane )

Misal

C #

Köprü deseni, ağaç yapısındaki nesneleri oluşturur. Soyutlamayı uygulamadan ayırır. Burada soyutlama, nesnelerin çağrılacağı müşteriyi temsil eder. C # 'da uygulanan bir örnek aşağıda verilmiştir.

// Gerçekten ayrıştırılmış mimari sağlamaya yardımcı olurhalka açık arayüz IBridge{    geçersiz İşlev1();    geçersiz Fonksiyon2();}halka açık sınıf Köprü1 : IBridge{    halka açık geçersiz İşlev1()    {        Konsol.Yazı çizgisi("Bridge1.Function1");    }    halka açık geçersiz Fonksiyon2()    {        Konsol.Yazı çizgisi("Bridge1.Function2");    }}halka açık sınıf Köprü2 : IBridge{    halka açık geçersiz İşlev1()    {        Konsol.Yazı çizgisi("Köprü2.Fonksiyon1");    }    halka açık geçersiz Fonksiyon2()    {        Konsol.Yazı çizgisi("Köprü2.Fonksiyon2");    }}halka açık arayüz IAbstractBridge{    geçersiz CallMethod1();    geçersiz CallMethod2();}halka açık sınıf AbstractBridge : IAbstractBridge{    halka açık IBridge köprü;    halka açık AbstractBridge(IBridge köprü)    {        bu.köprü = köprü;    }    halka açık geçersiz CallMethod1()    {        bu.köprü.İşlev1();    }    halka açık geçersiz CallMethod2()    {        bu.köprü.Fonksiyon2();    }}

Bridge sınıfları, nesneler oluşturmak için aynı arayüz odaklı mimariyi kullanan Uygulamalardır. Öte yandan, soyutlama, uygulama sınıfının bir örneğini alır ve yöntemini çalıştırır. Böylelikle birbirlerinden tamamen ayrılmışlardır.

Kristal

Öz sınıf Çizim API'si  Öz def draw_circle(x : Float64, y : Float64, yarıçap : Float64)sonsınıf ÇizimAPI1 < Çizim API'si  def draw_circle(x : Yüzer, y : Yüzer, yarıçap : Yüzer)    "API1.circle at #{x}:#{y} - yarıçap: #{yarıçap}"  sonsonsınıf ÇizimAPI2 < Çizim API'si  def draw_circle(x : Float64, y : Float64, yarıçap : Float64)    "API2.circle at #{x}:#{y} - yarıçap: #{yarıçap}"  sonsonÖz sınıf Şekil  korumalı alıcı drawing_api : Çizim API'si  def başlatmak(@drawing_api)  son  Öz def çizmek  Öz def resize_by_percentage(yüzde : Float64)sonsınıf Çember şeklinde < Şekil  alıcı x : Float64  alıcı y : Float64  alıcı yarıçap : Float64  def başlatmak(@x, @y, @radius, drawing_api : Çizim API'si)    Süper(drawing_api)  son  def çizmek    @drawing_api.draw_circle(@x, @y, @radius)  son  def resize_by_percentage(yüzde : Float64)    @radius *= (1 + yüzde/100)  sonsonsınıf BridgePattern  def kendini.Ölçek    şekiller = [] nın-nin Şekil    şekiller << Çember şeklinde.yeni(1.0, 2.0, 3.0, ÇizimAPI1.yeni)    şekiller << Çember şeklinde.yeni(5.0, 7.0, 11.0, ÇizimAPI2.yeni)    şekiller.her biri yapmak |şekil|      şekil.resize_by_percentage(2.5)      koyar şekil.çizmek    son  sonsonBridgePattern.Ölçek

Çıktı

1.0: 2.0'daki API1.circle - yarıçap: 3.075API2. 5.0: 7.0'daki daire - yarıçap: 11.275

C ++

#Dahil etmek <iostream>#Dahil etmek <string>#Dahil etmek <vector>sınıf Çizim API'si {  halka açık:    gerçek ~Çizim API'si() = varsayılan;    gerçek std::dizi DrawCircle(yüzer x, yüzer y, yüzer yarıçap) sabit = 0;};sınıf ÇizimAPI01 : halka açık Çizim API'si {  halka açık:    std::dizi DrawCircle(yüzer x, yüzer y, yüzer yarıçap) sabit geçersiz kılmak {      dönüş "API01.circle at" + std::to_string(x) + ":" + std::to_string(y) +        "- yarıçap:" + std::to_string(yarıçap);     }};sınıf ÇizimAPI02 : halka açık Çizim API'si {  halka açık:    std::dizi DrawCircle(yüzer x, yüzer y, yüzer yarıçap) sabit geçersiz kılmak {      dönüş "API02.circle at" + std::to_string(x) + ":" + std::to_string(y) +        "- yarıçap:" + std::to_string(yarıçap);     }};sınıf Şekil {  halka açık:    Şekil(sabit Çizim API'si& drawing_api) : drawing_api_(drawing_api) {}    gerçek ~Şekil() = varsayılan;    gerçek std::dizi Çizmek() sabit = 0;    gerçek yüzer ResizeByPercentage(sabit yüzer yüzde) = 0;  korumalı:    sabit Çizim API'si& drawing_api_;};sınıf Çember şeklinde: halka açık Şekil {  halka açık:        Çember şeklinde(yüzer x, yüzer y, yüzer yarıçap, sabit Çizim API'si& drawing_api)      : Şekil(drawing_api), x_(x), y_(y), yarıçap_(yarıçap) {}    std::dizi Çizmek() sabit geçersiz kılmak {        dönüş drawing_api_.DrawCircle(x_, y_, yarıçap_);    }    yüzer ResizeByPercentage(sabit yüzer yüzde) geçersiz kılmak {      dönüş yarıçap_ *= (1.0f + yüzde/100.0f);    }    özel:    yüzer x_, y_, yarıçap_;};int ana(int argc, kömür** argv) {  std::vektör<Çember şeklinde> şekiller {    Çember şeklinde{1.0f, 2.0f, 3.0f, ÇizimAPI01{}},    Çember şeklinde{5.0f, 7.0f, 11.0f, ÇizimAPI02{}}  };   için (Oto& şekil: şekiller) {    şekil.ResizeByPercentage(2.5);    std::cout << şekil.Çizmek() << std::son;  }  dönüş 0;}

Çıktı:

API01. Daire 1.000000: 2.000000 - yarıçap: 3.075000API02. Daire 5.000000: 7.000000 - yarıçap: 11.275000

Java

Aşağıdaki Java programı, hesap işlemlerini bu işlemlerin günlüğe kaydedilmesinden ayıran bir banka hesabı tanımlar.

// Logger'ın iki uygulaması vardır: bilgi ve uyarı@FunctionalInterfacearayüz Ağaç kesicisi {    geçersiz günlük(Dize İleti);        statik Ağaç kesicisi bilgi() {        dönüş İleti -> Sistemi.dışarı.println("bilgi:" + İleti);    }    statik Ağaç kesicisi uyarı() {        dönüş İleti -> Sistemi.dışarı.println("uyarı:" + İleti);    }}Öz sınıf Özet Hesap {    özel Ağaç kesicisi ağaç kesicisi = Ağaç kesicisi.bilgi();        halka açık geçersiz setLogger(Ağaç kesicisi ağaç kesicisi) {        bu.ağaç kesicisi = ağaç kesicisi;    }        // günlük bölümü, Logger uygulamasına devredilir    korumalı geçersiz işletmek(Dize İleti, Boole sonuç) {        ağaç kesicisi.günlük(İleti + "sonuç" + sonuç);    }}sınıf SimpleAccount genişler Özet Hesap {    özel int denge;        halka açık SimpleAccount(int denge) {        bu.denge = denge;    }        halka açık Boole isBalanceLow() {        dönüş denge < 50;    }        halka açık geçersiz Çekil(int Miktar) {        Boole shouldPerform = denge >= Miktar;        Eğer (shouldPerform) {            denge -= Miktar;        }        işletmek("Çekil " + Miktar, shouldPerform);    }}halka açık sınıf BridgeDemo {    halka açık statik geçersiz ana(Dize[] argümanlar) {        SimpleAccount hesap = yeni SimpleAccount(100);        hesap.Çekil(75);                Eğer (hesap.isBalanceLow()) {            // ayrıca çalışma zamanında Logger uygulamasını da değiştirebilirsiniz            hesap.setLogger(Ağaç kesicisi.uyarı());        }                hesap.Çekil(10);        hesap.Çekil(100);    }}

Çıktı:

bilgi: geri çek 75 sonuç doğru uyarı: geri çek 10 sonuç doğru uyarı: geri çek 100 sonuç yanlış

PHP

arayüz Çizim API'si{    işlevi drawCircle($ x, y, $ yarıçap);}sınıf ÇizimAPI1 uygular Çizim API'si{    halka açık işlevi drawCircle($ x, y, $ yarıçap)    {        Eko "API1.circle at $ x:y yarıçap $ yarıçap. n";    }}sınıf ÇizimAPI2 uygular Çizim API'si{    halka açık işlevi drawCircle($ x, y, $ yarıçap)    {        Eko "API2.circle at $ x:y yarıçap $ yarıçap. n";    }}Öz sınıf Şekil{    korumalı $ drawingAPI;    halka açık Öz işlevi çizmek();    halka açık Öz işlevi resizeByPercentage($ pct);    korumalı işlevi __construct(Çizim API'si $ drawingAPI)    {        $ this->drawingAPI = $ drawingAPI;    }}sınıf Çember şeklinde genişler Şekil{    özel $ x;    özel y;    özel $ yarıçap;    halka açık işlevi __construct($ x, y, $ yarıçap, Çizim API'si $ drawingAPI)    {        ebeveyn::__construct($ drawingAPI);        $ this->x = $ x;        $ this->y = y;        $ this->yarıçap = $ yarıçap;    }    halka açık işlevi çizmek()    {        $ this->drawingAPI->drawCircle($ this->x, $ this->y, $ this->yarıçap);    }    halka açık işlevi resizeByPercentage($ pct)    {        $ this->yarıçap *= $ pct;    }}sınıf Test cihazı{    halka açık statik işlevi ana()    {        $ şekiller = dizi(            yeni Çember şeklinde(1, 3, 7,  yeni ÇizimAPI1()),            yeni Çember şeklinde(5, 7, 11, yeni ÇizimAPI2()),        );        her biri için ($ şekiller gibi $ şekil) {            $ şekil->resizeByPercentage(2.5);            $ şekil->çizmek();        }    }}Test cihazı::ana();

Çıktı:

API1. Daire 1: 3 yarıçap 17,5 API2. Daire 5: 7 yarıçap 27,5

Scala

kişisel özellik Çizim API'si {  def drawCircle(x: Çift, y: Çift, yarıçap: Çift)}sınıf ÇizimAPI1 genişler Çizim API'si {  def drawCircle(x: Çift, y: Çift, yarıçap: Çift) = println(s "API # 1 $ xy$ yarıçap")}sınıf ÇizimAPI2 genişler Çizim API'si {  def drawCircle(x: Çift, y: Çift, yarıçap: Çift) = println(s "API # 2 $ xy$ yarıçap")}Öz sınıf Şekil(drawingAPI: Çizim API'si) {  def çizmek()  def yeniden boyutlandırma Yüzdesi(pct: Çift)}sınıf Çember şeklinde(x: Çift, y: Çift, var yarıçap: Çift, drawingAPI: Çizim API'si)    genişler Şekil(drawingAPI: Çizim API'si) {  def çizmek() = drawingAPI.drawCircle(x, y, yarıçap)  def yeniden boyutlandırma Yüzdesi(pct: Çift) { yarıçap *= pct }}nesne BridgePattern {  def ana(argümanlar: Dizi[Dize]) {    Sıra (	yeni Çember şeklinde(1, 3, 5, yeni ÇizimAPI1),	yeni Çember şeklinde(4, 5, 6, yeni ÇizimAPI2)    ) her biri için { x =>        x.yeniden boyutlandırma Yüzdesi(3)        x.çizmek()			      }	  }}

Python

"""Köprü düzeni örneği."""itibaren ABC ithalat ABCMeta, soyutlama yöntemiUYGULANMADI = "Bunu uygulamalısın."sınıf Çizim API'si:    __metaclass__ = ABCMeta    @hayalhanemersin    def draw_circle(kendini, x, y, yarıçap):        yükseltmek NotImplementedError(UYGULANMADI)sınıf ÇizimAPI1(Çizim API'si):    def draw_circle(kendini, x, y, yarıçap):        dönüş f"API1.circle at {x}:{y} - yarıçap: {radius}"sınıf ÇizimAPI2(Çizim API'si):    def draw_circle(kendini, x, y, yarıçap):        dönüş f"API2.circle at {x}:{y} - yarıçap: {radius}"sınıf ÇizimAPI3(Çizim API'si):    def draw_circle(kendini, x, y, yarıçap):        dönüş f"API3.circle at {x}:{y} - yarıçap: {radius}"sınıf Şekil:    __metaclass__ = ABCMeta    drawing_api = Yok    def __içinde__(kendini, drawing_api):        kendini.drawing_api = drawing_api    @hayalhanemersin    def çizmek(kendini):        yükseltmek NotImplementedError(UYGULANMADI)    @hayalhanemersin    def resize_by_percentage(kendini, yüzde):        yükseltmek NotImplementedError(UYGULANMADI)sınıf Çember şeklinde(Şekil):    def __içinde__(kendini, x, y, yarıçap, drawing_api):        kendini.x = x        kendini.y = y        kendini.yarıçap = yarıçap        Süper(Çember şeklinde, kendini).__içinde__(drawing_api)    def çizmek(kendini):        dönüş kendini.drawing_api.draw_circle(kendini.x, kendini.y, kendini.yarıçap)    def resize_by_percentage(kendini, yüzde):        kendini.yarıçap *= 1 + yüzde / 100sınıf BridgePattern:    @hayalhanemersin    def Ölçek():        şekiller = [            Çember şeklinde(1.0, 2.0, 3.0, ÇizimAPI1()),            Çember şeklinde(5.0, 7.0, 11.0, ÇizimAPI2()),            Çember şeklinde(5.0, 4.0, 12.0, ÇizimAPI3()),        ]        için şekil içinde şekiller:            şekil.resize_by_percentage(2.5)            Yazdır(şekil.çizmek())BridgePattern.Ölçek()

Ayrıca bakınız

Referanslar

  1. ^ Gama, E, Dümen, R, Johnson, R, Vlissides, J: Tasarım desenleri, sayfa 151. Addison-Wesley, 1995
  2. ^ Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides (1994). Tasarım Desenleri: Yeniden Kullanılabilir Nesne Tabanlı Yazılımın Unsurları. Addison Wesley. pp.151ff. ISBN  0-201-63361-2.CS1 Maint: birden çok isim: yazarlar listesi (bağlantı)
  3. ^ "Köprü tasarım modeli - Sorun, Çözüm ve Uygulanabilirlik". w3sDesign.com. Alındı 2017-08-12.
  4. ^ "Köprü tasarım modeli - Yapı ve İşbirliği". w3sDesign.com. Alındı 2017-08-12.

Dış bağlantılar