欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++設(shè)計(jì)模式編程中使用Bridge橋接模式的完全攻略

 更新時(shí)間:2016年03月13日 09:57:21   投稿:goldensun  
這篇文章主要介紹了C++設(shè)計(jì)模式編程中使用Bridge橋接模式的完全攻略,Bridge將抽象部分與它的實(shí)現(xiàn)部分分離,使它們都可以獨(dú)立地變化需要的朋友可以參考下

橋接模式將抽象(Abstraction)與實(shí)現(xiàn)(Implementation)分離,使得二者可以獨(dú)立地變化。

橋接模式典型的結(jié)構(gòu)圖為:

201631395440751.jpg (557×221)

在橋接模式的結(jié)構(gòu)圖中可以看到,系統(tǒng)被分為兩個(gè)相對(duì)獨(dú)立的部分,左邊是抽象部分,右邊是實(shí)現(xiàn)部分,這兩個(gè)部分可以互相獨(dú)立地進(jìn)行修改:例如上面問(wèn)題中的客戶需求變化,當(dāng)用戶需求需要從 Abstraction 派生一個(gè)具體子類時(shí)候,并不需要像上面通過(guò)繼承方式實(shí)現(xiàn)時(shí)候需要添加子類 A1 和 A2 了。另外當(dāng)上面問(wèn)題中由于算法添加也只用改變右邊實(shí)現(xiàn)(添加一個(gè)具體化子類),而右邊不用在變化,也不用添加具體子類了。

一切都變得 elegant!

橋接模式號(hào)稱設(shè)計(jì)模式中最難理解的模式之一,關(guān)鍵就是這個(gè)抽象和實(shí)現(xiàn)的分離非常讓人奇怪,大部分人剛看到這個(gè)定義的時(shí)候都會(huì)認(rèn)為實(shí)現(xiàn)就是繼承自抽象,那怎么可能將他們分離呢。

《大話設(shè)計(jì)模式》中就Bridge模式的解釋:

手機(jī)品牌和軟件是兩個(gè)概念,不同的軟件可以在不同的手機(jī)上,不同的手機(jī)可以有相同的軟件,兩者都具有很大的變動(dòng)性。如果我們單獨(dú)以手機(jī)品牌或手機(jī)軟件為基類來(lái)進(jìn)行繼承擴(kuò)展的話,無(wú)疑會(huì)使類的數(shù)目劇增并且耦合性很高,(如果更改品牌或增加軟件都會(huì)增加很多的變動(dòng))兩種方式的結(jié)構(gòu)如下:

201631395516057.png (552×343)

201631395538456.jpg (572×317)

所以將兩者抽象出來(lái)兩個(gè)基類分別是PhoneBrand和PhoneSoft,那么在品牌類中聚合一個(gè)軟件對(duì)象的基類將解決軟件和手機(jī)擴(kuò)展混亂的問(wèn)題,這樣兩者的擴(kuò)展就相對(duì)靈活,剪短了兩者的必要聯(lián)系,結(jié)構(gòu)圖如下:

201631395621451.png (590×245)

這樣擴(kuò)展品牌和軟件就相對(duì)靈活獨(dú)立,達(dá)到解耦的目的!

抽象基類及接口:

1、Abstraction::Operation():定義要實(shí)現(xiàn)的操作接口

2、AbstractionImplement::Operation():實(shí)現(xiàn)抽象類Abstaction所定義操作的接口,由其具體派生類ConcreteImplemenA、ConcreteImplemenA或者其他派生類實(shí)現(xiàn)。

3、在Abstraction::Operation()中根據(jù)不同的指針多態(tài)調(diào)用AbstractionImplement::Operation()函數(shù)。

理解:
Bridge用于將表示和實(shí)現(xiàn)解耦,兩者可以獨(dú)立的變化.在Abstraction類中維護(hù)一個(gè)AbstractionImplement類指針,需要采用不同的實(shí)現(xiàn)方式的時(shí)候只需要傳入不同的AbstractionImplement派生類就可以了.

Bridge的實(shí)現(xiàn)方式其實(shí)和Builde十分的相近,可以這么說(shuō):本質(zhì)上是一樣的,只是封裝的東西不一樣罷了.兩者的實(shí)現(xiàn)都有如下的共同點(diǎn):

抽象出來(lái)一個(gè)基類,這個(gè)基類里面定義了共有的一些行為,形成接口函數(shù)(對(duì)接口編程而不是對(duì)實(shí)現(xiàn)編程),這個(gè)接口函數(shù)在Buildier中是BuildePart函數(shù)在Bridge中是Operation函數(shù);

其次,聚合一個(gè)基類的指針,如Builder模式中Director類聚合了一個(gè)Builder基類的指針,而B(niǎo)rige模式中Abstraction類聚合了一個(gè)AbstractionImplement基類的指針(優(yōu)先采用聚合而不是繼承);

而在使用的時(shí)候,都把對(duì)這個(gè)類的使用封裝在一個(gè)函數(shù)中,在Bridge中是封裝在Director::Construct函數(shù)中,因?yàn)檠b配不同部分的過(guò)程是一致的,而在Bridge模式中則是封裝在Abstraction::Operation函數(shù)中,在這個(gè)函數(shù)中調(diào)用對(duì)應(yīng)的AbstractionImplement::Operation函數(shù).就兩個(gè)模式而言,Builder封裝了不同的生成組成部分的方式,而B(niǎo)ridge封裝了不同的實(shí)現(xiàn)方式.

橋接模式就將實(shí)現(xiàn)與抽象分離開(kāi)來(lái),使得RefinedAbstraction依賴于抽象的實(shí)現(xiàn),這樣實(shí)現(xiàn)了依賴倒轉(zhuǎn)原則,而不管左邊的抽象如何變化,只要實(shí)現(xiàn)方法不變,右邊的具體實(shí)現(xiàn)就不需要修改,而右邊的具體實(shí)現(xiàn)方法發(fā)生變化,只要接口不變,左邊的抽象也不需要修改。


優(yōu)點(diǎn)
1.將實(shí)現(xiàn)抽離出來(lái),再實(shí)現(xiàn)抽象,使得對(duì)象的具體實(shí)現(xiàn)依賴于抽象,滿足了依賴倒轉(zhuǎn)原則。

2.將可以共享的變化部分,抽離出來(lái),減少了代碼的重復(fù)信息。

3.對(duì)象的具體實(shí)現(xiàn)可以更加靈活,可以滿足多個(gè)因素變化的要求。

缺點(diǎn)
客戶必須知道選擇哪一種類型的實(shí)現(xiàn)。
設(shè)計(jì)中有超過(guò)一維的變化我們就可以用橋模式。如果只有一維在變化,那么我們用繼承就可以圓滿的解決問(wèn)題。

代碼示例:

Abstraction.h

#ifndef _ABSTRACTION_H_
#define _ABSTRACTION_H_

class AbstractionImplement;

class Abstraction
{
public:
  virtual void Operation()=0;//定義接口,表示該類所支持的操作
  virtual ~Abstraction();
protected:
  Abstraction();
};

class RefinedAbstractionA:public Abstraction
{
public:
  RefinedAbstractionA(AbstractionImplement* imp);//構(gòu)造函數(shù)
  virtual void Operation();//實(shí)現(xiàn)接口
  virtual ~RefinedAbstractionA();//析構(gòu)函數(shù)
private:
  AbstractionImplement* _imp;//私有成員
};

class RefinedAbstractionB:public Abstraction
{
public:
  RefinedAbstractionB(AbstractionImplement* imp);//構(gòu)造函數(shù)
  virtual void Operation();//實(shí)現(xiàn)接口
  virtual ~RefinedAbstractionB();//析構(gòu)函數(shù)
private:
  AbstractionImplement* _imp;//私有成員
};
#endif

Abstraction.cpp
#include "Abstraction.h"
#include "AbstractionImplement.h"
#include <iostream>

using namespace std;

Abstraction::Abstraction()
{}

Abstraction::~Abstraction()
{}

RefinedAbstractionA::RefinedAbstractionA(AbstractionImplement* imp)
{
  this->_imp = imp;
}

RefinedAbstractionA::~RefinedAbstractionA()
{
  delete this->_imp;
  this->_imp = NULL;
}

void RefinedAbstractionA::Operation()
{
  cout << "RefinedAbstractionA::Operation" << endl;
  this->_imp->Operation();
}

RefinedAbstractionB::RefinedAbstractionB(AbstractionImplement* imp)
{
  this->_imp = imp;
}

RefinedAbstractionB::~RefinedAbstractionB()
{
  delete this->_imp;
  this->_imp = NULL;
}

void RefinedAbstractionB::Operation()
{
  cout << "RefinedAbstractionB::Operation" << endl;
  this->_imp->Operation();
}

AbstractImplement.h
#ifndef _ABSTRACTIONIMPLEMENT_H_
#define _ABSTRACTIONIMPLEMENT_H_

//抽象基類,定義了實(shí)現(xiàn)的接口
class AbstractionImplement
{
public:
  virtual void Operation()=0;//定義操作接口
  virtual ~AbstractionImplement();
protected:
  AbstractionImplement();
};

// 繼承自AbstractionImplement,是AbstractionImplement的不同實(shí)現(xiàn)之一
class ConcreteAbstractionImplementA:public AbstractionImplement
{
public:
  ConcreteAbstractionImplementA();
  void Operation();//實(shí)現(xiàn)操作
  ~ConcreteAbstractionImplementA();
protected:
};

// 繼承自AbstractionImplement,是AbstractionImplement的不同實(shí)現(xiàn)之一
class ConcreteAbstractionImplementB:public AbstractionImplement
{
public:
  ConcreteAbstractionImplementB();
  void Operation();//實(shí)現(xiàn)操作
  ~ConcreteAbstractionImplementB();
protected:
};
#endif

AbstractImplement.cpp
#include "AbstractionImplement.h"
#include <iostream>

using namespace std;

AbstractionImplement::AbstractionImplement()
{}

AbstractionImplement::~AbstractionImplement()
{}

ConcreteAbstractionImplementA::ConcreteAbstractionImplementA()
{}

ConcreteAbstractionImplementA::~ConcreteAbstractionImplementA()
{}

void ConcreteAbstractionImplementA::Operation()
{
  cout << "ConcreteAbstractionImplementA Operation" << endl;
}

ConcreteAbstractionImplementB::ConcreteAbstractionImplementB()
{}

ConcreteAbstractionImplementB::~ConcreteAbstractionImplementB()
{}

void ConcreteAbstractionImplementB::Operation()
{
  cout << "ConcreteAbstractionImplementB Operation" << endl;
}

main.cpp

#include "Abstraction.h"
#include "AbstractionImplement.h"
#include <iostream>

using namespace std;

int main()
{
  /* 將抽象部分與它的實(shí)現(xiàn)部分分離,使得它們可以獨(dú)立地變化

  1、抽象Abstraction與實(shí)現(xiàn)AbstractionImplement分離;

  2、抽象部分Abstraction可以變化,如new RefinedAbstractionA(imp)、new RefinedAbstractionB(imp2);

  3、實(shí)現(xiàn)部分AbstractionImplement也可以變化,如new ConcreteAbstractionImplementA()、new ConcreteAbstractionImplementB();

  */

  AbstractionImplement* imp = new ConcreteAbstractionImplementA();    //實(shí)現(xiàn)部分ConcreteAbstractionImplementA
  Abstraction* abs = new RefinedAbstractionA(imp);            //抽象部分RefinedAbstractionA
  abs->Operation();

  cout << "-----------------------------------------" << endl;

  AbstractionImplement* imp1 = new ConcreteAbstractionImplementB();    //實(shí)現(xiàn)部分ConcreteAbstractionImplementB
  Abstraction* abs1 = new RefinedAbstractionA(imp1);            //抽象部分RefinedAbstractionA
  abs1->Operation();

  cout << "-----------------------------------------" << endl;

  AbstractionImplement* imp2 = new ConcreteAbstractionImplementA();    //實(shí)現(xiàn)部分ConcreteAbstractionImplementA
  Abstraction* abs2 = new RefinedAbstractionB(imp2);            //抽象部分RefinedAbstractionB
  abs2->Operation();

  cout << "-----------------------------------------" << endl;

  AbstractionImplement* imp3 = new ConcreteAbstractionImplementB();    //實(shí)現(xiàn)部分ConcreteAbstractionImplementB
  Abstraction* abs3 = new RefinedAbstractionB(imp3);            //抽象部分RefinedAbstractionB
  abs3->Operation();

  cout << endl;
  return 0;
}

代碼說(shuō)明:
Bridge模式將抽象和實(shí)現(xiàn)分別獨(dú)立實(shí)現(xiàn),在代碼中就是Abstraction類和AbstractionImplement類。

使用組合(委托)的方式將抽象和實(shí)現(xiàn)徹底地解耦,這樣的好處是抽象和實(shí)現(xiàn)可以分別獨(dú)立地變化,系統(tǒng)的耦合性也得到了很好的降低。
GoF的那句話中的“實(shí)現(xiàn)”該怎么去理解:“實(shí)現(xiàn)”特別是和“抽象”放在一起的時(shí)候我們“默認(rèn)”的理解是“實(shí)現(xiàn)”就是“抽象”的具體子類的實(shí)現(xiàn),但是這里GoF所謂的“實(shí)現(xiàn)”的含義不是指抽象基類的具體子類對(duì)抽象基類中虛函數(shù)(接口)的實(shí)現(xiàn),是和繼承結(jié)合在一起的。而這里的“實(shí)現(xiàn)”的含義指的是怎么去實(shí)現(xiàn)用戶的需求,并且指的是通過(guò)組合(委托)的方式實(shí)現(xiàn)的,因此這里的實(shí)現(xiàn)不是指的繼承基類、實(shí)現(xiàn)基類接口,而是指的是通過(guò)對(duì)象組合實(shí)現(xiàn)用戶的需求。

實(shí)際上上面使用Bridge模式和使用帶來(lái)問(wèn)題方式的解決方案的根本區(qū)別在于是通過(guò)繼承還是通過(guò)組合的方式去實(shí)現(xiàn)一個(gè)功能需求。

備注:

由于實(shí)現(xiàn)的方式有多種,橋接模式的核心就是把這些實(shí)現(xiàn)獨(dú)立出來(lái),讓他們各自變化。

將抽象部分與它的實(shí)現(xiàn)部分分離:實(shí)現(xiàn)系統(tǒng)可能有多角度(維度)分類,每一種分類都可能變化,那么就把這種多角度分離出來(lái)讓它們獨(dú)立變化,減少它們之間的耦合。

在發(fā)現(xiàn)需要多角度去分類實(shí)現(xiàn)對(duì)象,而只用繼承會(huì)造成大量的類增加,不能滿足開(kāi)放-封閉原則時(shí),就要考慮用Bridge橋接模式了。

合成/聚合復(fù)用原則:盡量使用合成/聚合,精良不要使用類繼承。
優(yōu)先使用對(duì)象的合成/聚合將有助于保持每個(gè)類被封裝,并被集中在單個(gè)任務(wù)上。這樣類和類繼承層次會(huì)保持較小規(guī)模,并且不太可能增長(zhǎng)為不可控制的龐然大物。

適用場(chǎng)景:

  • 你不希望在抽象和它的實(shí)現(xiàn)部分之間有一個(gè)固定的綁定關(guān)系。例如這種情況可能是因?yàn)椋诔绦蜻\(yùn)行時(shí)刻實(shí)現(xiàn)部分應(yīng)可以被選擇或者切換。
  • 類的抽象以及它的實(shí)現(xiàn)都應(yīng)該可以通過(guò)生成子類的方法加以擴(kuò)充。這時(shí)B r i d g e 模式使你可以對(duì)不同的抽象接口和實(shí)現(xiàn)部分進(jìn)行組合,并分別對(duì)它們進(jìn)行擴(kuò)充。
  • 對(duì)一個(gè)抽象的實(shí)現(xiàn)部分的修改應(yīng)對(duì)客戶不產(chǎn)生影響,即客戶的代碼不必重新編譯。
  • (C + +)你想對(duì)客戶完全隱藏抽象的實(shí)現(xiàn)部分。在C + +中,類的表示在類接口中是可見(jiàn)的。
  • 有許多類要生成。這樣一種類層次結(jié)構(gòu)說(shuō)明你必須將一個(gè)對(duì)象分解成兩個(gè)部分。R u m b a u g h 稱這種類層次結(jié)構(gòu)為“嵌套的普化”(nested generalizations )。
  • 你想在多個(gè)對(duì)象間共享實(shí)現(xiàn)(可能使用引用計(jì)數(shù)),但同時(shí)要求客戶并不知道這一點(diǎn)。一個(gè)簡(jiǎn)單的例子便是C o p l i e n 的S t r i n g 類[ C o p 9 2 ],在這個(gè)類中多個(gè)對(duì)象可以共享同一個(gè)字符串表示(S t r i n g R e p )。

相關(guān)文章

  • 詳解C++中變量的初始化規(guī)則

    詳解C++中變量的初始化規(guī)則

    這篇文章詳細(xì)介紹了關(guān)于C++中變量的初始化規(guī)則,C++如果不對(duì)變量初始化,可能會(huì)導(dǎo)致很多后果,所以學(xué)習(xí)C++變量初始化規(guī)則就很重要了,下面一起來(lái)看看
    2016-08-08
  • C++二級(jí)指針和指針的引用

    C++二級(jí)指針和指針的引用

    這篇文章主要介紹了C++二級(jí)指針和指針的引用,下文舉例實(shí)現(xiàn)形參指針改變實(shí)參指針?biāo)赶虻膶?duì)象,需要的小伙伴可以參考一下,希望對(duì)你的學(xué)習(xí)有所幫助
    2022-03-03
  • C語(yǔ)言 makefile學(xué)習(xí)及實(shí)現(xiàn)實(shí)例

    C語(yǔ)言 makefile學(xué)習(xí)及實(shí)現(xiàn)實(shí)例

    這篇文章主要介紹了C語(yǔ)言 makefile學(xué)習(xí)及實(shí)現(xiàn)實(shí)例的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • C語(yǔ)言新手練習(xí)之多維數(shù)組、結(jié)構(gòu)體及函數(shù)

    C語(yǔ)言新手練習(xí)之多維數(shù)組、結(jié)構(gòu)體及函數(shù)

    這篇文章主要給大家介紹了關(guān)于C語(yǔ)言新手練習(xí)之多維數(shù)組、結(jié)構(gòu)體及函數(shù)的相關(guān)資料,這些內(nèi)容在我們?nèi)粘i_(kāi)發(fā)中經(jīng)常會(huì)遇到的,需要的朋友可以參考下
    2021-06-06
  • C語(yǔ)言實(shí)現(xiàn)數(shù)據(jù)結(jié)構(gòu)迷宮實(shí)驗(yàn)

    C語(yǔ)言實(shí)現(xiàn)數(shù)據(jù)結(jié)構(gòu)迷宮實(shí)驗(yàn)

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)數(shù)據(jù)結(jié)構(gòu)迷宮實(shí)驗(yàn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-03-03
  • C語(yǔ)言實(shí)現(xiàn)opencv提取直線、輪廓及ROI實(shí)例詳解

    C語(yǔ)言實(shí)現(xiàn)opencv提取直線、輪廓及ROI實(shí)例詳解

    這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)opencv提取直線、輪廓及ROI實(shí)例詳解,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2018-01-01
  • VC下通過(guò)系統(tǒng)快照實(shí)現(xiàn)進(jìn)程管理的方法

    VC下通過(guò)系統(tǒng)快照實(shí)現(xiàn)進(jìn)程管理的方法

    這篇文章主要介紹了VC下通過(guò)系統(tǒng)快照實(shí)現(xiàn)進(jìn)程管理的方法,較為詳細(xì)的講述了VC下通過(guò)系統(tǒng)快照實(shí)現(xiàn)進(jìn)程管理的原理與具體實(shí)現(xiàn)方法,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2014-10-10
  • C++11 智能指針的具體使用

    C++11 智能指針的具體使用

    本文主要介紹了C++11 智能指針的具體使用,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • C++實(shí)現(xiàn)酒店管理系統(tǒng)

    C++實(shí)現(xiàn)酒店管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)酒店管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • 實(shí)例詳解C++中指針與引用的區(qū)別

    實(shí)例詳解C++中指針與引用的區(qū)別

    引用是C++引入的重要機(jī)制(C語(yǔ)言沒(méi)有引用),它使原來(lái)在C中必須用指針來(lái)實(shí)現(xiàn)的功能有了另一種實(shí)現(xiàn)的選擇,在書(shū)寫(xiě)形式上更為簡(jiǎn)潔,那么引用的本質(zhì)是什么,它與指針又有什么關(guān)系呢?這篇文章主要給大家介紹了關(guān)于C++中指針與引用的區(qū)別,需要的朋友可以參考下
    2021-07-07

最新評(píng)論