程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++設計模式之建造者模式(一)

C++設計模式之建造者模式(一)

編輯:C++入門知識

C++設計模式之建造者模式(一)


在內蒙古這遼闊的草原上,放養著成千上萬的奶牛。蒙牛集團在這裡崛起,迅速搶占中國大半牛奶市場,造就了一個商業帝國。蒙牛集團牛奶生產流程大致是這樣的: 放養奶牛--->牛奶加工--->牛奶包裝--->銷售。經歷從放養奶牛到進行市場銷售這一系列環節,蒙牛牛奶才得以誕生。雖然生產流程比這個流程還復雜,但對客戶而言,根本不需要知道牛奶生產的細節,只需要到超市購買就行了。在設計模式中,也存在一個類似的模式,封裝了產品創建的一系列操作過程,客戶端無需知道這些操作流程就可以直接使用這個產品,稱之為建造者模式。


1、建造者模式概述

建造者模式是較為復雜的創建型模式,它將客戶端與包含多個組成部分(或部件)的復雜對象的創建過程分離,客戶端無須知道復雜對象的內部組成部分與裝配方式,只需要知道所需建造者的類型即可。它關注如何一步一步創建一個的復雜對象,不同的具體建造者定義了不同的創建過程,且具體建造者相互獨立,增加新的建造者非常方便,無須修改已有代碼,系統具有較好的擴展性。例如:用戶不需要知道電腦的具體制造流程,而直接使用電腦就可以了,電腦具體制造流程對用戶來說就相當於一個黑盒子。

建造者模式定義如下:

建造者模式(Builder Pattern):將一個復雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。建造者模式是一種對象創建型模式。

建造者模式一步一步創建一個復雜的對象,它允許用戶只通過指定復雜對象的類型和內容就可以構建它們,用戶不需要知道內部的具體構建細節。

\

建造者模式結構圖

在建造者模式結構圖中包含如下幾個角色:

Builder(抽象建造者):它為創建一個產品Product對象的各個部件指定抽象接口,在該接口中一般聲明兩類方法,一類方法是buildPartX(),它們用於創建復雜對象的各個部件;另一類方法是getResult(),它們用於返回復雜對象。Builder既可以是抽象類,也可以是接口。

ConcreteBuilder(具體建造者):它實現了Builder接口,實現各個部件的具體構造和裝配方法,定義並明確它所創建的復雜對象,也可以提供一個方法返回創建好的復雜產品對象。

Product(產品角色):它是被構建的復雜對象,包含多個組成部件,具體建造者創建該產品的內部表示並定義它的裝配過程。

Director(指揮者):指揮者又稱為導演類,它負責安排復雜對象的建造次序,指揮者與抽象建造者之間存在關聯關系,可以在其construct()建造方法中調用建造者對象的部件構造與裝配方法,完成復雜對象的建造。客戶端一般只需要與指揮者進行交互,在客戶端確定具體建造者的類型,並實例化具體建造者對象,然後通過指揮者類的構造函數或者Setter方法將該對象傳入指揮者類中。

在建造者模式的定義中提到了復雜對象,那麼什麼是復雜對象?簡單來說,復雜對象是指那些包含多個成員屬性的對象,這些成員屬性也稱為部件或零件,如汽車包括方向盤、發動機、輪胎等部件;電子郵件包括發件人、收件人、主題、內容、附件等部件;Socket數據包包含包頭、包體、包尾等部件;XML配置文件包含頭部信息、數據體、尾部信息等部件。


2、暴風影音播放器的設計與實現

現需要開發一款類似暴風影音的播放器,該播放軟件提供多種界面顯示模式,如完整模式、精簡模式、記憶模式等。在不同的顯示模式下主界面的組成元素有所差異,如在完整模式下將顯示菜單、播放列表、主窗口、控制條等;在精簡模式下只顯示主窗口和控制條;而在記憶模式下將顯示主窗口、控制條、收藏列表等。嘗試使用建造者模式設計該軟件。

\

暴風影音播放器是具體的產品,該產品包含菜單、主窗口、播放列表、播放進度條、收藏列表等部件。 暴風影音播放器.h頭文件代碼如下:
#ifndef _PLAYER_H_
#define _PLAYER_H_
#include 
#include 
using namespace std;

//播放器
class Player
{
private:
	string m_strMenu;			//菜單欄
	string m_strWindow;			//主窗口
	string m_strPlayList;			//播放列表
	string m_strControlBar;			//進度條
	string m_strCollectList;		//收藏列表
public:
	//設置部件
	void SetMenu(string strMenu);
	void SetWindow(string strWindow);
	void SetPlayList(string strPlayList);
	void SetControlBar(string strControlBar);
	void SetCollectList(string strCollectList);

	//獲取各部件
	string GetMenu();
	string GetWindow();
	string GetPlayList();
	string GetControlBar();
	string GetCollectList();

	//顯示播放器窗口包含的部件
	void Display();
};

#endif
暴風影響播放器Cpp文件代碼如下:
#include "Player.h"

//設置主菜單部件
void Player::SetMenu(string strMenu)
{
	m_strMenu = strMenu;
}

//設置主窗口部件
void Player::SetWindow(string strWindow)
{
	m_strWindow = strWindow;
}

//設計播放列表部件
void Player::SetPlayList(string strPlayList)
{
	m_strPlayList = strPlayList;
}

//設置滾動條部件
void Player::SetControlBar(string strControlBar)
{
	m_strControlBar = strControlBar;
}

//設置收藏列表部件
void Player::SetCollectList(string strCollectList)
{
	m_strCollectList = strCollectList;
}

//獲取主菜單部件
string Player::GetMenu()
{
	return m_strMenu;
}

//獲取主窗口部件
string Player::GetWindow()
{
	return m_strWindow;
}

//獲取播放列表部件
string Player::GetPlayList()
{
	return m_strPlayList;
}

//獲取滾動條部件
string Player::GetControlBar()
{
	return m_strControlBar;
}


//獲取收藏列表部件
string Player::GetCollectList()
{
	return m_strCollectList;
}

//顯示播放器窗口包含的部件
void Player::Display()
{
	cout << "---" << m_strWindow << endl;
	cout << "---" << m_strMenu << endl;
	cout << "---" << m_strPlayList << endl;
	cout << "---" << m_strControlBar << endl;
	cout << "---" << m_strCollectList << endl << endl;
}
暴風影音播放器能在完整模式、精簡模式、記憶模式三種模式下播放,各播放模式下,暴風影音的部件不相同。考慮到擴展性,可以定義一個抽象播放模式類,該抽象類中定義了一系列創建具體播放部件的方法。具體的三種播放模式繼承於這個抽象播放模式類。 播放模式.h頭文件代碼如下:
#ifndef _PLAY_PATTERN_H_
#define _PLAY_PATTERN_H_
#include 
#include 
#include "Player.h"
using namespace std;

//抽象播放模式
class PlayPattern
{
protected:
	//具體產品(播放器)
	Player * m_pPlayer;
public:
	PlayPattern()
	{
		m_pPlayer = new Player();
	}

	~PlayPattern()
	{
		if( NULL != m_pPlayer )
		{
			delete m_pPlayer;

			m_pPlayer = NULL;
		}
	}
	
	//制造播放窗口
	virtual void BuildWindow() = 0;

	//制造播放菜單
	virtual void BuildMenu() = 0;

	//制造播放列表
	virtual void BuildPlayList() = 0;

	//制造播放進度條
	virtual void BuildControlBar() = 0;

	//制造收藏列表
	virtual void BuildCollectList() = 0;

	//獲取產品(播放器)
	Player * GetPlayer()
	{
		return m_pPlayer;
	}
};


//完整播放模式
class FullPattern : public PlayPattern
{
public:
	void BuildWindow();
	void BuildMenu();
	void BuildPlayList();
	void BuildControlBar();
	void BuildCollectList();
};


//精簡播放模式
class SimplePattern : public PlayPattern
{
public:
	void BuildWindow();
	void BuildMenu();
	void BuildPlayList();
	void BuildControlBar();
	void BuildCollectList();
};


//記憶播放模式
class MemoryPattern : public PlayPattern
{
public:
	void BuildWindow();
	void BuildMenu();
	void BuildPlayList();
	void BuildControlBar();
	void BuildCollectList();
};

#endif
播放模式Cpp文件代碼如下:
#include "PlayPattern.h"

//制造播放窗口
void FullPattern::BuildWindow()
{
	m_pPlayer->SetWindow("主界面窗口");
}

//制造播放菜單
void FullPattern::BuildMenu()
{
	m_pPlayer->SetMenu("主菜單");
}

//制造播放列表
void FullPattern::BuildPlayList()
{
	m_pPlayer->SetPlayList("播放列表");
}

//制造播放進度條
void FullPattern::BuildControlBar()
{
	m_pPlayer->SetControlBar("進度條");
}

//制造收藏列表
void FullPattern::BuildCollectList()
{
	m_pPlayer->SetCollectList(" ");
}

////////////////精簡模式///////////////////////////////

void SimplePattern::BuildWindow()
{
	m_pPlayer->SetWindow("主界面窗口");
}

void SimplePattern::BuildMenu()
{
	m_pPlayer->SetMenu(" ");
}

void SimplePattern::BuildPlayList()
{
	m_pPlayer->SetPlayList(" ");
}

void SimplePattern::BuildControlBar()
{
	m_pPlayer->SetControlBar("進度條");
}

void SimplePattern::BuildCollectList()
{
	m_pPlayer->SetCollectList(" ");
}

/////////////////記憶模式////////////////////////////////

void MemoryPattern::BuildWindow()
{
	m_pPlayer->SetWindow("主界面窗口");
}

void MemoryPattern::BuildMenu()
{
	m_pPlayer->SetMenu(" ");
}

void MemoryPattern::BuildPlayList()
{
	m_pPlayer->SetPlayList(" ");
}

void MemoryPattern::BuildControlBar()
{
	m_pPlayer->SetControlBar("進度條");
}

void MemoryPattern::BuildCollectList()
{
	m_pPlayer->SetCollectList("收藏列表");
}
在建造者模式的結構中還引入了一個指揮者類Director,用於控制產品的創建過程。本例中ContructManage就是播放器指揮類。用戶需要哪種類型的播放模式,只需要創建一個具體的播放模式,然後把這個播放模式傳入到播放器指揮者中就可以了,由播放器指揮者處理一系列過程的建造。
暴風影音播放器指揮者類.h頭文件實現如下:
#ifndef _CONTRUCT_MANAGE_H_
#define _CONTRUCT_MANAGE_H_
#include "PlayPattern.h"
#include "Player.h"

//建造管理器
class ContructManage
{
private:
	//具體建造者
	PlayPattern * m_pPlayPattern;
public:
	//設置播放模式
	void SetPlayPattern(PlayPattern * pPlayPattern);

	//封裝建造過程
	Player * Construct();
};

#endif
暴風影音播放器指揮者類Cpp文件實現如下:
#include "ContructManage.h"

//設置播放模式
void ContructManage::SetPlayPattern(PlayPattern * pPlayPattern)
{
	m_pPlayPattern = pPlayPattern;
}

//封裝建造過程
Player * ContructManage::Construct()
{
	m_pPlayPattern->BuildWindow();
	m_pPlayPattern->BuildMenu();
	m_pPlayPattern->BuildPlayList();
	m_pPlayPattern->BuildControlBar();
	m_pPlayPattern->BuildCollectList();

	Player * pPlayer = m_pPlayPattern->GetPlayer();
	return pPlayer;
}
測試文件實現代碼如下:
#include 
#include "ContructManage.h"
#include "PlayPattern.h"
#include "Player.h"
using namespace std;

int main()
{
        /***********************創建建造管理器**********************/
	ContructManage * pContructManage = new ContructManage();
	Player * pPlayer = NULL;

	/***********************完整播放模式************************/
	PlayPattern * pFullPattern = new FullPattern();
	cout << "完整播放模式:" << endl;
	pContructManage->SetPlayPattern(pFullPattern);
	pPlayer = pContructManage->Construct();
	pPlayer->Display();

	/***********************精簡播放模式************************/
	PlayPattern * pSimplePattern = new SimplePattern();
	cout << "精簡播放模式:" << endl;
	pContructManage->SetPlayPattern(pSimplePattern);
	pPlayer = pContructManage->Construct();
	pPlayer->Display();

	/***********************記憶播放模式************************/
	PlayPattern * pMemoryPattern = new MemoryPattern();
	cout << "記憶播放模式:" << endl;
	pContructManage->SetPlayPattern(pMemoryPattern);
	pPlayer = pContructManage->Construct();
	pPlayer->Display();

	/***********************銷毀操作****************************/
	cout << endl;
	delete pFullPattern;
	pFullPattern = NULL;

	delete pSimplePattern;
	pSimplePattern = NULL;

	delete pMemoryPattern;
	pMemoryPattern = NULL;

	delete pContructManage;
	pContructManage = NULL;

	return 0;
}
編譯並執行,程序結果如下: n丁編程,客戶端根據需要傳入具體的建造者類型,指揮者將指導具體建造者一步一步構造一個完整的產品(逐步調用具體建造者的buildX()方法),相同的構造過程可以創建完全不同的產品。在暴風影音播放器實例中,如果需要更換具體的播放模式,只需要把具體播放模式傳入到播放器指揮者中即可,可以隨時切換播放模式;如果需要增加新的播放模式,可以增加一個新的播放模式類作為抽象播放模式子類,並把該播放模式傳入到播放器指揮者中,原有代碼無須修改,完全符合“開閉原則”。
未完、更新中......


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved