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 <iostream>
#include <string>
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 <iostream>
#include <string>
#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 <iostream>
#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;
}
编译并执行,程序结果如下:

    在建造者模式中,客户端只需实例化指挥者类,指挥者类针对抽象建造者编程,客户端根据需要传入具体的建造者类型,指挥者将指导具体建造者一步一步构造一个完整的产品(逐步调用具体建造者的buildX()方法),相同的构造过程可以创建完全不同的产品。在暴风影音播放器实例中,如果需要更换具体的播放模式,只需要把具体播放模式传入到播放器指挥者中即可,可以随时切换播放模式;如果需要增加新的播放模式
,可以增加一个新的播放模式类作为抽象播放模式子类,并把该播放模式传入到播放器指挥者中,原有代码无须修改,完全符合“开闭原则”。

    未完、更新中......


  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
建造者模式是一种创建型设计模式,它允许您创建不同类型的对象,而无需暴露对象的创建逻辑。它将对象的构建步骤分解为可重用的部分,并允许您按顺序执行它们。这使得您能够创建具有不同属性的对象,而无需编写大量的重复代码。 在建造者模式中,有一个建造者类,它负责创建对象的特定部分,如电脑的CPU、内存和硬盘等。该类具有一个公共接口,该接口定义了每个部分的构建步骤。在构建步骤完成后,该类可以返回一个完整的对象。 建造者模式也包括一个指导者类,它负责调用建造者类的构建步骤,并按照正确的顺序执行它们。指导者类知道如何创建对象,但不知道如何创建对象的每个部分,因此它将这个工作委托给建造者类。 以下是一个简单的C++实现建造者模式的示例代码: ```cpp #include <iostream> #include <string> class Computer { public: void setCPU(const std::string& cpu) { m_cpu = cpu; } void setMemory(const std::string& memory) { m_memory = memory; } void setHardDisk(const std::string& hardDisk) { m_hardDisk = hardDisk; } void show() { std::cout << "CPU: " << m_cpu << std::endl; std::cout << "Memory: " << m_memory << std::endl; std::cout << "Hard Disk: " << m_hardDisk << std::endl; } private: std::string m_cpu; std::string m_memory; std::string m_hardDisk; }; class Builder { public: virtual ~Builder() {} virtual void buildCPU() = 0; virtual void buildMemory() = 0; virtual void buildHardDisk() = 0; virtual Computer* getResult() = 0; }; class Director { public: void setBuilder(Builder* builder) { m_builder = builder; } void construct() { m_builder->buildCPU(); m_builder->buildMemory(); m_builder->buildHardDisk(); } private: Builder* m_builder; }; class DesktopBuilder : public Builder { public: DesktopBuilder() { m_computer = new Computer; } ~DesktopBuilder() { delete m_computer; } void buildCPU() { m_computer->setCPU("Intel Core i7"); } void buildMemory() { m_computer->setMemory("16GB DDR4 RAM"); } void buildHardDisk() { m_computer->setHardDisk("2TB SATA Hard Disk"); } Computer* getResult() { return m_computer; } private: Computer* m_computer; }; int main() { Director director; DesktopBuilder desktopBuilder; director.setBuilder(&desktopBuilder); director.construct(); Computer* computer = desktopBuilder.getResult(); computer->show(); return 0; } ``` 在这个示例中,我们创建了一个Computer类,它有三个成员变量:CPU、内存和硬盘。我们还创建了一个Builder类,它定义了创建Computer对象的构建步骤,并且为每个部分提供了一个抽象接口。我们还创建了一个Director类,它负责调用建造者类的构建步骤,并按照正确的顺序执行它们。 在具体的建造者实现中,我们创建了一个DesktopBuilder类,它实现了Builder接口,并具有一个Computer成员变量。在DesktopBuilder类的构建步骤中,我们设置了Computer对象的CPU、内存和硬盘。最后,我们返回一个完整的Computer对象。 在main函数中,我们创建了一个Director对象,并将DesktopBuilder对象传递给setBuilder函数。然后我们调用construct函数,它将调用DesktopBuilder的构建步骤,并返回一个完整的Computer对象。我们最后打印出这个对象的属性,以验证它是否被正确构建。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值