天天看點

大話設計模式22----合成/聚合複用原則 & 橋接模式大話設計模式

大話設計模式

1 合成/聚合複用原則

概念:盡量使用合成/聚合,盡量不要使用類繼承。【J&DP】

聚合:表示一種弱的“擁有關系”,展現的是A對象可以包含B對象,但B對象不是A對象的一部分;

合成:表示一種強的“擁有關系”,展現了嚴格的部分和整體的關系,部分和整體的聲明周期一樣。

大話設計模式22----合成/聚合複用原則 & 橋接模式大話設計模式

合成/聚合複用原則的好處:優先使用對象的合成/聚合将有助于你保持每個類被封裝,并被集中在單個任務上。這樣的類和類繼承層次保持較小的規模,并且不大可能增長為不可控制的龐然大物。【DP】

繼承的缺點:對象的繼承關系是在編譯時就定義好了,是以無法再運作時改變從父類繼承的實作。子類的實作與它的父類有非常緊密的依賴關系,以至于父類實作中的任何變化會導緻子類發生變化。當你需要複用子類的時候,如果繼承下來的實作不适合解決新的問題,則父類必須重寫或被其它更合适的類替換。這種依賴關系限制了靈活性并最終限制了複用性。

1.2 C++代碼實作

1.2.1 程式結構圖

大話設計模式22----合成/聚合複用原則 & 橋接模式大話設計模式

1.2.2 C++源代碼

HandsetSoft.h類:

#ifndef _HANDSET_SOFT_H_
#define _HANDSET_SOFT_H_

class HandsetSoft
{
public:
	virtual void run() = 0;
};

class HandsetGame :public HandsetSoft
{
public:
	void run() override;
};

class HandsetAddressedList :public HandsetSoft
{
public:
	void run() override;
};
#endif
           

HandsetSoft.cpp類

#include"HandsetSoft.h"
#include<iostream>

using std::cout;
using std::endl;

void HandsetGame::run()
{
	cout << "運作遊戲" << endl;
}

void HandsetAddressedList::run()
{
	cout << "運作通訊錄" << endl;
}
           

HandsetBrand.h類

#ifndef _HANDSET_BRAND_H_
#define _HANDSET_BRAND_H_

class HandsetSoft;

class HandsetBrand
{
protected:
	HandsetSoft *soft;//為簡單起見,隻為該品牌手機增加一個功能,實際上可以通過vector/list增加多個軟體
public:
	virtual void run() = 0;
	void setHandsetSoft(HandsetSoft *soft);
};

class HandsetBrandM:public HandsetBrand
{
public:
	void run() override;
};

class HandsetBrandN:public HandsetBrand
{
public:
	void run() override;
};

#endif
           

HandsetBrand.cpp類

#include"HandsetBrand.h"
#include"HandsetSoft.h"
#include<iostream>

using std::cout;
using std::endl;

void HandsetBrand::setHandsetSoft(HandsetSoft *soft)
{
	this->soft = soft;
}

void HandsetBrandM::run()
{
	cout << "品牌M:";
	soft->run();
}

void HandsetBrandN::run()
{
	cout << "品牌N:";
	soft->run();
}
           

用戶端Client.cpp

#include"HandsetBrand.h"
#include"HandsetSoft.h"
#include<iostream>
using namespace std;

int main()
{
	HandsetSoft *game = new HandsetGame();
	HandsetSoft *addressed = new HandsetAddressedList();

	HandsetBrand *m = new HandsetBrandM();
	HandsetBrand *n = new HandsetBrandN();

	m->setHandsetSoft(game);
	m->run();
	m->setHandsetSoft(addressed);
	m->run();

	n->setHandsetSoft(game);
	n->run();
	n->setHandsetSoft(addressed);
	n->run();

	delete game;
	delete addressed;
	delete m;
	delete n;

	system("pause");
	return 0;
}
           

運作結果:

品牌M:運作遊戲
品牌M:運作通訊錄
品牌N:運作遊戲
品牌N:運作通訊錄
請按任意鍵繼續. . .
           

此時,不管是在增加一個品牌還是增加一個軟體,都隻需增加一個類即可,而不用更改源代碼,滿足封閉-開放原則,而如果單純用繼承的話,不管是手機品牌繼承軟體還是手機軟體繼承品牌,當增加其中一個品牌或者軟體的時候,都需要更改類,不滿足封閉-開放原則。

如按照品牌來分:

大話設計模式22----合成/聚合複用原則 &amp; 橋接模式大話設計模式

按軟體來分:

大話設計模式22----合成/聚合複用原則 &amp; 橋接模式大話設計模式

2 橋接模式

2.1 橋接模式(Bridge)結構圖

大話設計模式22----合成/聚合複用原則 &amp; 橋接模式大話設計模式

2,2 對橋接模式的一些解釋

概念:将抽象部分與它的實作部分分離,使它們都可以獨立地變化【DP】。如上方的手機品牌和手機軟的抽象類聚合。

抽象和它的實作分離并不是說讓抽象類和其他派生類分離,而是值抽象類和它的派生類用來實作自己的對象【DPE】?由于實作的方式有多種(如按軟體分和按手機品牌分),橋接模式的核心意圖就是把這些實作獨立出來,讓它們各自的變化。這使得每種實作的變化不會影響其他的實作,進而達到對應變化的目的。

實作系統可能有多角度分類,每一種分類都有可能變化,那麼就把這種多角度分離出來讓它們獨立變化,減少他們之間的耦合。

繼續閱讀