程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> C++設計形式編程中應用Bridge橋接形式的完整攻略

C++設計形式編程中應用Bridge橋接形式的完整攻略

編輯:關於C++

C++設計形式編程中應用Bridge橋接形式的完整攻略。本站提示廣大學習愛好者:(C++設計形式編程中應用Bridge橋接形式的完整攻略)文章只能為提供參考,不一定能成為您想要的結果。以下是C++設計形式編程中應用Bridge橋接形式的完整攻略正文


橋接形式將籠統(Abstraction)與完成(Implementation)分別,使得兩者可以自力地變更。

橋接形式典范的構造圖為:

在橋接形式的構造圖中可以看到,體系被分為兩個絕對自力的部門,右邊是籠統部門,左邊是完成部門,這兩個部門可以相互自力地停止修正:例如下面成績中的客戶需求變更,當用戶需求須要從 Abstraction 派生一個詳細子類時刻,其實不須要像下面經由過程繼續方法完成時刻須要添加子類 A1 和 A2 了。別的當下面成績中因為算法添加也只用轉變左邊完成(添加一個詳細化子類),而左邊不消在變更,也不消添加詳細子類了。

一切都變得 elegant!

橋接形式號稱設計形式中最難懂得的形式之一,症結就是這個籠統和完成的分別異常讓人奇異,年夜部門人剛看到這個界說的時刻都邑以為完成就是繼續自籠統,那怎樣能夠將他們分別呢。

《年夜話設計形式》中就Bridge形式的說明:

手機品牌和軟件是兩個概念,分歧的軟件可以在分歧的手機上,分歧的手機可以有雷同的軟件,二者都具有很年夜的更改性。假如我們零丁以手機品牌或手機軟件為基類來停止繼續擴大的話,無疑會使類的數量劇增而且耦合性很高,(假如更改品牌或增長軟件都邑增長許多的更改)兩種方法的構造以下:

所以將二者籠統出來兩個基類分離是PhoneBrand和PhoneSoft,那末在品牌類中聚合一個軟件對象的基類將處理軟件和手機擴大凌亂的成績,如許二者的擴大就絕對靈巧,剪短了二者的需要接洽,構造圖以下:

如許擴大品牌和軟件就絕對靈巧自力,到達解耦的目標!

籠統基類及接口:

1、Abstraction::Operation():界說要完成的操作接口

2、AbstractionImplement::Operation():完成籠統類Abstaction所界說操作的接口,由其詳細派生類ConcreteImplemenA、ConcreteImplemenA或許其他派生類完成。

3、在Abstraction::Operation()中依據分歧的指針多態挪用AbstractionImplement::Operation()函數。

懂得:
Bridge用於將表現和完成解耦,二者可以自力的變更.在Abstraction類中保護一個AbstractionImplement類指針,須要采取分歧的完成方法的時刻只須要傳入分歧的AbstractionImplement派生類便可以了.

Bridge的完成方法其實和Builde非常的鄰近,可以這麼說:實質上是一樣的,只是封裝的器械紛歧樣而已.二者的完成都有以下的配合點:

籠統出來一個基類,這個基類外面界說了共有的一些行動,構成接口函數(對接口編程而不是對完成編程),這個接口函數在Buildier中是BuildePart函數在Bridge中是Operation函數;

其次,聚合一個基類的指針,如Builder形式中Director類聚合了一個Builder基類的指針,而Brige形式中Abstraction類聚合了一個AbstractionImplement基類的指針(優先采取聚合而不是繼續);

而在應用的時刻,都把對這個類的應用封裝在一個函數中,在Bridge中是封裝在Director::Construct函數中,由於拆卸分歧部門的進程是分歧的,而在Bridge形式中則是封裝在Abstraction::Operation函數中,在這個函數中挪用對應的AbstractionImplement::Operation函數.就兩個形式而言,Builder封裝了分歧的生成構成部門的方法,而Bridge封裝了分歧的完成方法.

橋接形式就將完成與籠統分別開來,使得RefinedAbstraction依附於籠統的完成,如許完成了依附倒轉准繩,而不論右邊的籠統若何變更,只需完成辦法不變,左邊的詳細完成就不須要修正,而左邊的詳細完成辦法產生變更,只需接口不變,右邊的籠統也不須要修正。


長處
1.將完成抽離出來,再完成籠統,使得對象的詳細完成依附於籠統,知足了依附倒轉准繩。

2.將可以同享的變更部門,抽離出來,削減了代碼的反復信息。

3.對象的詳細完成可以加倍靈巧,可以知足多個身分變更的請求。

缺陷
客戶必需曉得選擇哪種類型的完成。
設計中有跨越一維的變更我們便可以用橋形式。假如只要一維在變更,那末我們用繼續便可以美滿的處理成績。

代碼示例:

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);//結構函數
  virtual void Operation();//完成接口
  virtual ~RefinedAbstractionA();//析構函數
private:
  AbstractionImplement* _imp;//公有成員
};

class RefinedAbstractionB:public Abstraction
{
public:
  RefinedAbstractionB(AbstractionImplement* imp);//結構函數
  virtual void Operation();//完成接口
  virtual ~RefinedAbstractionB();//析構函數
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_

//籠統基類,界說了完成的接口
class AbstractionImplement
{
public:
  virtual void Operation()=0;//界說操作接口
  virtual ~AbstractionImplement();
protected:
  AbstractionImplement();
};

// 繼續自AbstractionImplement,是AbstractionImplement的分歧完成之一
class ConcreteAbstractionImplementA:public AbstractionImplement
{
public:
  ConcreteAbstractionImplementA();
  void Operation();//完成操作
  ~ConcreteAbstractionImplementA();
protected:
};

// 繼續自AbstractionImplement,是AbstractionImplement的分歧完成之一
class ConcreteAbstractionImplementB:public AbstractionImplement
{
public:
  ConcreteAbstractionImplementB();
  void Operation();//完成操作
  ~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()
{
  /* 將籠統部門與它的完成部門分別,使得它們可以自力地變更

  1、籠統Abstraction與完成AbstractionImplement分別;

  2、籠統部門Abstraction可以變更,如new RefinedAbstractionA(imp)、new RefinedAbstractionB(imp2);

  3、完成部門AbstractionImplement也能夠變更,如new ConcreteAbstractionImplementA()、new ConcreteAbstractionImplementB();

  */

  AbstractionImplement* imp = new ConcreteAbstractionImplementA();    //完成部門ConcreteAbstractionImplementA
  Abstraction* abs = new RefinedAbstractionA(imp);            //籠統部門RefinedAbstractionA
  abs->Operation();

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

  AbstractionImplement* imp1 = new ConcreteAbstractionImplementB();    //完成部門ConcreteAbstractionImplementB
  Abstraction* abs1 = new RefinedAbstractionA(imp1);            //籠統部門RefinedAbstractionA
  abs1->Operation();

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

  AbstractionImplement* imp2 = new ConcreteAbstractionImplementA();    //完成部門ConcreteAbstractionImplementA
  Abstraction* abs2 = new RefinedAbstractionB(imp2);            //籠統部門RefinedAbstractionB
  abs2->Operation();

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

  AbstractionImplement* imp3 = new ConcreteAbstractionImplementB();    //完成部門ConcreteAbstractionImplementB
  Abstraction* abs3 = new RefinedAbstractionB(imp3);            //籠統部門RefinedAbstractionB
  abs3->Operation();

  cout << endl;
  return 0;
}

代碼解釋:
Bridge形式將籠統和完成分離自力完成,在代碼中就是Abstraction類和AbstractionImplement類。

應用組合(拜托)的方法將籠統和完成完全地解耦,如許的利益是籠統和完成可以分離自力地變更,體系的耦合性也獲得了很好的下降。
GoF的那句話中的“完成”該怎樣去懂得:“完成”特殊是和“籠統”放在一路的時刻我們“默許”的懂得是“完成”就是“籠統”的詳細子類的完成,然則這裡GoF所謂的“完成”的寄義不是指籠統基類的詳細子類對籠統基類中虛函數(接口)的完成,是和繼續聯合在一路的。而這裡的“完成”的寄義指的是怎樣去完成用戶的需求,而且指的是經由過程組合(拜托)的方法完成的,是以這裡的完成不是指的繼續基類、完成基類接口,而是指的是經由過程對象組合完成用戶的需求。

現實上下面應用Bridge形式和應用帶來成績方法的處理計劃的基本差別在因而經由過程繼續照樣經由過程組合的方法去完成一個功效需求。

備注:

因為完成的方法有多種,橋接形式的焦點就是把這些完成自力出來,讓他們各自變更。

將籠統部門與它的完成部門分別:完成體系能夠有多角度(維度)分類,每種分類都能夠變更,那末就把這類多角度分別出來讓它們自力變更,削減它們之間的耦合。

在發明須要多角度去分類完成對象,而只用繼續會形成年夜量的類增長,不克不及知足開放-關閉准繩時,就要斟酌用Bridge橋接形式了。

分解/聚合復用准繩:盡可能應用分解/聚合,優良不要應用類繼續。
優先應用對象的分解/聚合將有助於堅持每一個類被封裝,並被集中在單個義務上。如許類和類繼續條理會堅持較小范圍,而且不太能夠增加為弗成掌握的龐然年夜物。

實用場景:

  • 你不願望在籠統和它的完成部門之間有一個固定的綁定關系。例如這類情形能夠是由於,在法式運轉時辰完成部門應可以被選擇或許切換。
  • 類的籠統和它的完成都應當可以經由過程生成子類的辦法加以擴大。這時候B r i d g e 形式使你可以對分歧的籠統接口和完成部門停止組合,並分離對它們停止擴大。
  • 對一個籠統的完成部門的修正應對客戶不發生影響,即客戶的代碼不用從新編譯。
  • (C + +)你想對客戶完整隱蔽籠統的完成部門。在C + +中,類的表現在類接口中是可見的。
  • 有很多類要生成。如許一品種條理構造解釋你必需將一個對象分化成兩個部門。R u m b a u g h 稱這類類條理構造為“嵌套的普化”(nested generalizations )。
  • 你想在多個對象間同享完成(能夠應用援用計數),但同時請求客戶其實不曉得這一點。一個簡略的例子就是C o p l i e n 的S t r i n g 類[ C o p 9 2 ],在這個類中多個對象可以同享統一個字符串表現(S t r i n g R e p )。
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved