[c/c++]design mode

本文详细介绍了C/C++中的23种设计模式,包括创建型模式(如工厂方法、抽象工厂、单例、建造者、原型模式)、结构型模式(适配器、装饰器、代理、外观、桥接、组合、享元模式)和行为型模式(策略、模板、观察者、迭代子、责任链、命令、备忘录、状态、访问者、中介者、解释器模式)。设计模式是解决软件设计中常见问题的通用解决方案,通过这些模式可以提高代码的可维护性和可复用性。
摘要由CSDN通过智能技术生成
#include <Windows.h>
#include <stdio.h>

#include<list>
#include<map>

#include "alignment.h"

using namespace std;

#pragma pack(push)
#pragma pack(1)   



//C语言中并没有bool类型变量。这是C++中新增的系统类型
typedef enum _FLAG{
    FLAG_FALSE,
    FLAG_TRUE
}Flag;

typedef enum _CHIPSET_TYPE {
    CHIPSET_UNKOWN = 0,
    LOWEND_CHIPSET_Q,
    LOWEND_CHIPSET_M,
    HIGHEND_CHIPSET_Q,
    HIGHEND_CHIPSET_M
}CHIPSET_TYPE;

//芯片
class cChipset{
public:
    virtual void printMsg() = 0;
};

//低端芯片Q
class cLowendChipsetQ :public cChipset {
public:
    void printMsg() {
        printf("Low-end Chipset Q\n");
    }
};

//低端芯片M
class cLowendChipsetM :public cChipset {
public:
    void printMsg() {
        printf("Low-end Chipset M\n");
    }
};

//高端芯片Q
class cHighendChipsetQ :public cChipset {
public:
    void printMsg() {
        printf("High-end Chipset Q\n");
    }
};

//高端芯片M
class cHighendChipsetM :public cChipset {
public:
    void printMsg() {
        printf("High-end Chipset M\n");
    }
};

一.创建型模式(5种)

0.简单工厂模式(不属于涉及的23种模式)

需要在工厂类中做判断,从而创造相应的产品。当增加新的产品时,就需要修改工厂类

缺点:要增加新的产品时,就需要修改工厂类,这就违反了开放封闭原则

//建唯一的工厂,可以生产高低端芯片,在内部判断 
class cSimpleFactory {
public:
	cChipset* processChipset(CHIPSET_TYPE type) {
		cChipset* pChipset = NULL;

		switch (type){
		case LOWEND_CHIPSET_Q:
			 pChipset = new cLowendChipsetQ();
			 break;
		case LOWEND_CHIPSET_M:
			 pChipset = new cLowendChipsetM();
			 break;
		case HIGHEND_CHIPSET_Q:
			 pChipset = new cHighendChipsetQ();
			 break;
		case HIGHEND_CHIPSET_M:
			pChipset = new cHighendChipsetM();
			break;
		default:
			printf("OEM does not support this chipset type\n");
			break;
		}
		
		return pChipset;
	}
};
int main()
{
	printf("测试0:简单工厂模式\n");
	CHIPSET_TYPE tp = LOWEND_CHIPSET_Q; //
	cSimpleFactory* pSF = new cSimpleFactory();
	cChipset* pLC0 = pSF->processChipset(tp);
	if (pLC0 != NULL) {
		pLC0->printMsg();
	}
}

 

1.工厂方法模式(Factory Method)

定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类

缺点:每增加一种产品,就需要增加一个对象的工厂.相比简单工厂模式,工厂方法模式需要定义更多的类

class cFactoryMethod {
public:
	virtual cChipset* processChipset() = 0;
};

//生产低端Q芯片的工厂
class cFactoryMethodLowendQ :public cFactoryMethod {
public:
	cLowendChipsetQ* processChipset() {
		return new cLowendChipsetQ();
	}
};

//生产低端M芯片的工厂
class cFactoryMethodLowendM :public cFactoryMethod {
public:
	cLowendChipsetM* processChipset() {
		return new cLowendChipsetM();
	}
};

//生产高端Q芯片的工厂
class cFactoryMethodHighendQ :public cFactoryMethod {
public:
	cHighendChipsetQ* processChipset() {
		return new cHighendChipsetQ();
	}
};

//生产高端M芯片的工厂
class cFactoryMethodHighendM :public cFactoryMethod {
public:
	cHighendChipsetM* processChipset() {
		return new cHighendChipsetM();
	}
};
int main()
{
	printf("测试1:工厂方法模式\n");
	cFactoryMethod* pFM = new cFactoryMethodLowendM(); //
	cChipset* pLC1 = pFM->processChipset();
	pLC1->printMsg();
}

 

2.抽象工厂模式

提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类

class cAbstractFactory {
public:
	virtual cChipset* processLowChipset() = 0;
	virtual cChipset* processHighChipset() = 0;
};

//生产低端和高端Q芯片的工厂
class cAbstractFactoryQ :public cAbstractFactory {
public:
	cLowendChipsetQ* processLowChipset() {
		return new cLowendChipsetQ();
	}

	cHighendChipsetQ* processHighChipset() {
		return new cHighendChipsetQ();
	}
};

//生产低端和高端M芯片的工厂
class cAbstractFactoryM :public cAbstractFactory {
public:
	cLowendChipsetM* processLowChipset() {
		return new cLowendChipsetM();
	}

	cHighendChipsetM* processHighChipset() {
		return new cHighendChipsetM();
	}
};
int main()
{
	printf("测试2:抽象工厂模式\n");
	cAbstractFactory* pAF = new cAbstractFactoryM();  //
	cChipset* pLC2 = pAF->processLowChipset();
	pLC2->printMsg();
	cChipset* pHC2 = pAF->processHighChipset();
	pHC2->printMsg();
}

 

3.单例模式

保证一个类仅有一个实例

class cSingleDecoder {
public:
	static cSingleDecoder* initInstance(const char* componentName);
	static void uninitInstance();
	virtual void doDocode() = 0;
protected:           //必须为保护,如果是私有属性,子类无法访问父类的构造函数
	cSingleDecoder() {};
private:
	static cSingleDecoder* pDecoder; //唯一实例的指针
};

class cDecoderAVC :public cSingleDecoder {
	friend class cSingleDecoder; //必须为友元类,否则父类无法访问子类的构造函数
public:
	void doDocode() {
		printf("do cDecoderAVC::doDocode for:%p\n",this);
	}
private:                    //为私有属性,这样外界无法通过构造函数进行实例化
	cDecoderAVC() {}
};

class cDecoderHEVC :public cSingleDecoder {
	friend class cSingleDecoder; //必须为友元类,否则父类无法访问子类的构造函数
public:
	void doDocode() {
		printf("do cDecoderAVC::cDecoderHEVC for:%p\n", this);
	}
private:                    //为私有属性,这样外界无法通过构造函数进行实例化
	cDecoderHEVC() {}
};

const char* COMPONENT_AVC = "OMX.google.video.decoder.avc";
const char* COMPONENT_HEVC = "OMX.google.video.decoder.hevc";

cSingleDecoder* cSingleDecoder::pDecoder = NULL;
cSingleDecoder* cSingleDecoder::initInstance(const char* componentName)
{
	printf("initInstance,pDecoder:%p\n",pDecoder);
	//todo:非线程安全,加lock
	if (pDecoder == NULL){
		if (strcmp(componentName, COMPONENT_AVC) == 0) {
			pDecoder = new cDecoderAVC();
		}
		else if (strcmp(componentName, COMPONENT_HEVC) == 0) {
			pDecoder = new cDecoderHEVC();
		}	
	}
	//todo:加unlock

	return pDecoder;
}

void cSingleDecoder::uninitInstance() {
	printf("uninitInstance,pDecoder:%p\n",pDecoder);
	if (pDecoder != NULL) {
		delete pDecoder;
		pDecoder = NULL;
	}
}
int main()
{
	printf("测试3:单例模式\n");
	const char* pName_HEVC = COMPONENT_HEVC;//
	const char* pName_AVC = COMPONENT_AVC;
	cSingleDecoder* pD1 = cSingleDecoder::initInstance(pName_HEVC);
	pD1->doDocode();
	cSingleDecoder* pD2 = cSingleDecoder::initInstance(COMPONENT_AVC);
	pD2->doDocode();
	cSingleDecoder::uninitInstance();
	cSingleDecoder *pD3 = cSingleDecoder::initInstance(COMPONENT_AVC);
	pD3->doDocode();
}

 

4.建造者模式

一个复杂对象的创建工作,由各个部分的子对象用一定的算法构成;由于需求变化,这个复杂对象的各个部分经常面临变化,但将它们组合在一起的算法却相对稳定

class cBuilderCodec {
public:
	virtual void createCodec(const char* name) = 0;
	virtual void configure(int width,int height) = 0;
	virtual void prepare() = 0;
	virtual void start() = 0;

	virtual void stop() = 0;
	virtual void release() = 0;
};

class cBuilderCodecHW :public cBuilderCodec {
public:
	void createCodec(const char* name) {
		printf("create hw codec:%s\n",name);
	}

	void configure(int width, int height) {
		printf("configure hw codec with width:%d,height:%d\n", width,height);
	}

	void prepare() {
		printf("prepare hw codec\n");
	}

	void start() {
		printf("start hw codec\n");
	}

	void stop() {
		printf("stop hw codec\n");
	}

	void release() {
		printf("release hw codec\n");
	}
};

class cBuilderCodecSW :public cBuilderCodec {
public:
	void createCodec(const char* name) {
		printf("create sw codec:%s\n", name);
	}

	void configure(int width, int height) {
		printf("configure sw codec with width:%d,height:%d\n", width, height);
	}

	void prepare() {
		printf("prepare sw codec\n");
	}

	void start() {
		printf("start sw codec\n");
	}

	void stop() {
		printf("stop sw codec\n");
	}

	void release() {
		printf("release sw codec\n");
	}

};

class cDirectorCodec {
public:
	cDirectorCodec(cBuilderCodec* cbc) {
		m_cbc = cbc;
	}

	void create(const char* name,int width,int height) {
		m_cbc->createCodec(name);
		m_cbc->configure(width,height);
		m_cbc->start();
	}

	void destory() {
		m_cbc->stop();
		m_cbc->release();
	}

private:
	cBuilderCodec* m_cbc;
};
int main()
{
	printf("测试4:建造者模式\n");
	const char* name = "qcom_avc";
	cBuilderCodecHW* pBC = new cBuilderCodecHW();//
	cDirectorCodec* pDC = new cDirectorCodec(pBC);
	pDC->create(name,1080,720);
	pDC->destory();
}

 

5.原型模式

思想就是将一个对象作为原型,对其进行复制、克隆,产生一个和原对象类似的新对象

情形可以考虑使用原型模式:
    (1)当new一个对象,非常繁琐复杂时,可以使用原型模式来进行复制一个对象。比如创建对象时,构造函数的参数很多,而自己又不完全的知道每个参数的意义,就可以使用原型模式来创建一个新的对象,不必去理会创建的过程。
    (2)当需要new一个新的对象,这个对象和现有的对象区别不大,我们就可以直接复制一个已有的对象,然后稍加修改。
    (3)当需要一个对象副本时,比如需要提供对象的数据,同时又需要避免外部对数据对象进行修改,那就拷贝一个对象副本供外部使用

class cPrototypeCodec {
public:
	virtual cPrototypeCodec* clone() = 0;
	virtual void showCodec() = 0;
};

class cPrototypeDecodec :public cPrototypeCodec {
public:
	cPrototypeDecodec(Flag bHW, char* mine)
		:m_hardware(bHW),m_mine(mine){
		printf("cCodec construct with paramters:is hardware:%d,mine:%s\n", m_hardware, m_mine);
	}

	cPrototypeDecodec(const cPrototypeDecodec& obj) {
		this->m_hardware = obj.m_hardware;
		this->m_mine = obj.m_mine;
		printf("cCodec copy construct:is hardware:%d,mine:%s\n", m_hardware, m_mine);
	}

	cPrototypeCodec* clone() {
		return new cPrototypeDecodec(*this);
	}

	void showCodec() {
		printf("[%p]is hardware:%d,mine:%s\n",this,m_hardware,m_mine);
	}

private:
	Flag m_hardware;
	char* m_mine;
};
int main()
{
	printf("测试5:原型模式\n");
	Flag flag = FLAG_TRUE;
	char mine[] = "video/avc";
	cPrototypeCodec *cPD1 = new cPrototypeDecodec(flag,mine);
	cPD1->showCodec();
	cPrototypeCodec *cPD2 = cPD1->clone();
	cPD2->showCodec();
}

 

二.结构型模式(7种)

6.适配器模式

通俗的讲就是当我们已经有了一些类,而这些类不能满足新的需求,此时就可以考虑是否能将现有的类适配成可以满足新需求的类。适配器类需要继承或依赖已有的类,实现想要的目标接口

案例:在STL中就用到了适配器模式。STL实现了一种数据结构,称为双端队列(deque),支持前后两段的插入与删除。
STL实现栈和队列时,没有从头开始定义它们,而是直接使用双端队列实现的。这里双端队列就扮演了适配器的角色。
队列用到了它的后端插入,前端删除。而栈用到了它的后端插入,后端删除

//双端队列
class cAdapterDeque{
public:
	void push_back(int x) { 
		printf("cAdapterDeque::push_back\n");
	}

	void push_front(int x) { 
		printf("cAdapterDeque::push_front\n");
	}

	void pop_back() { 
		printf("cAdapterDeque::pop_back\n");
	}

	void pop_front() {
		printf("cAdapterDeque::pop_front\n");
	}
};

//顺序容器
class cSequence{
public:
	virtual void push(int x) = 0;
	virtual void pop() = 0;
};


//6.1 对象适配器
//栈:先进后出
class cStack : public cSequence{
public:
	void push(int x) { 
		deque.push_back(x); 
	}

	void pop() { 
		deque.pop_back(); 
	}
private:
	cAdapterDeque deque; //双端队列
};
//队列:先进先出
class cQueue : public cSequence{
public:
	void push(int x) { 
		deque.push_back(x); 
	}
	
	void pop() { 
		deque.pop_front(); 
	}
private:
	cAdapterDeque deque; //双端队列
};

//6.2类适配器
//栈:先进后出
class cStack2 : public cSequence, private cAdapterDeque {
public:
	void push(int x) {
		push_back(x);
	}

	void pop() {
		pop_back();
	}
};
//队列:先进先出
class cQueue2 : public cSequence,private cAdapterDeque {
public:
	void push(int x) {
		push_back(x);
	}

	void pop() {
		pop_front();
	}
};
int main()
{	
        printf("测试6.1:适配器模式-对象适配\n");
	cSequence* cPSS1 = new cStack();
	cPSS1->push(1);
	cPSS1->pop();
	cSequence* cPSD1 = new cQueue();
	cPSD1->push(2);
	cPSD1->pop();

	printf("测试6.2:适配器模式-类适配\n");
	cSequence* cPSS2 = new cStack();
	cPSS2->push(1);
	cPSS2->pop();
	cSequence* cPSD2 = new cQueue();
	cPSD2->push(2);
	cPSD2->pop();
}

 

7.装饰器模式

动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活

案例:一个手机,允许你为手机添加特性,比如增加播放器、录像机等。一种灵活的设计方式是,将手机嵌入到另一对象中,由这个对象完成特性的添加,我们称这个嵌入的对象为装饰

//抽象手机类
class cVendorPhone{
public:
	cVendorPhone() {}
	virtual ~cVendorPhone() {}
	virtual void ShowDecorate() {}
};
//具体的QCOM手机类
class cQcomPhone : public cVendorPhone {
private:
	char* m_chipset; 
public:
	cQcomPhone(char* name) : m_chipset(name) {
		printf("cQcomPhone::cQcomPhone,m_chipset:%s\n", m_chipset);
	}
	~cQcomPhone() {
		printf("~cQcomPhone\n");
	}
	void ShowDecorate() { 
		printf("ShowDecorate of qcom phone m_chipset:%s \n", m_chipset);
	}
};
//具体的MTK手机类
class cMtkPhone : public cVendorPhone {
private:
	char* m_chipset;
public:
	cMtkPhone(char* name) : m_chipset(name) {
		printf("cMtkPhone::cMtkPhone,m_chipset:%s\n", m_chipset);
	}
	~cMtkPhone() {
		printf("~cMtkPhone\n");
	}
	void ShowDecorate() { 
		printf("ShowDecorate of mtk phone m_chipset:%s \n", m_chipset);
	}
};

//装饰类
class cDecoratorPhone : public cVendorPhone {  //也继承抽象手机类
private:
	cVendorPhone *m_phone;  //要装饰的手机
public:
	cDecoratorPhone(cVendorPhone *phone) : m_phone(phone) {
		printf("cDecoratorPhone\n");
	}
	virtual void ShowDecorate() {
		printf("cDecoratorPhone::ShowDecorate");
		m_phone->ShowDecorate(); 
	}
};
//具体的A装饰类
class DecoratorPhoneWithPlayer : public cDecoratorPhone {
public:
	DecoratorPhoneWithPlayer(cVendorPhone *phone) : cDecoratorPhone(phone) {
		printf("DecoratorPhoneWithPlayer::DecoratorPhoneWithPlayer\n");
	}
	void ShowDecorate() { 
		printf("DecoratorPhoneWithPlayer::ShowDecorate\n");
		cDecoratorPhone::ShowDecorate(); 
		AddDecorate();   //添加装饰Player
	}
private:
	void AddDecorate() {
		printf("add player decorate\n"); 
	} 
};
//具体的B装饰类
class DecoratorPhoneWithRecorder : public cDecoratorPhone {
public:
	DecoratorPhoneWithRecorder(cVendorPhone *phone) : cDecoratorPhone(phone) {
		printf("DecoratorPhoneWithRecorder::DecoratorPhoneWithRecorder\n");
	}
	void ShowDecorate() { 
		printf("DecoratorPhoneWithRecorder::ShowDecorate\n");
		cDecoratorPhone::ShowDecorate();
		AddDecorate(); //添加装饰Recorder
	}
private:
	void AddDecorate() { 
		printf("add recorder decorate\n");
	} 
};
int main()
{
	printf("测试7:装饰模式\n");
	char chipset[] = "sdm660";                     //
	cVendorPhone *phone = new cQcomPhone(chipset) ;//
	cVendorPhone *dpa = new DecoratorPhoneWithPlayer(phone);
	cVendorPhone *dpb = new DecoratorPhoneWithRecorder(dpa);
	dpb->ShowDecorate();
}

 

8.代理模式

为其它对象提供一种代理以控制这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介作用

对象的创建开销很大。避免一次性创建所有开销很大的对象,就可以运用代理模式,并不直接创建对象,而是创建对象的代理,待到真正需要使用对象时,仍由代理负责打开

class cCodec {
public:
	cCodec(char *name) {
		m_name = name;
	}

	virtual ~cCodec(){

	}

	virtual void show() = 0;

protected:
	char* m_name;
};

class cCodecHW :public cCodec {
public:
	cCodecHW(char *name) :cCodec(name) {

	}

	~cCodecHW() {

	}

	void show() {
		printf("show hw codec name:%s\n",m_name);
	}
private:
	//数据很大
};

class cCodecHWProxy :public cCodec {
public:
	cCodecHWProxy(char* name)
		:cCodec(name),
		m_hw_codec(NULL) {

	}

	~cCodecHWProxy() {

	}

	void show() {
		if (m_hw_codec == NULL) {
			m_hw_codec = new cCodecHW(m_name);
		}

		m_hw_codec->show();
	}
private:
	cCodecHW* m_hw_codec;
};
int main()
{
	printf("测试8:代理模式\n");
	char pName[] = "omx,qcom.avc.decoder";
	cCodec* pC = new cCodecHWProxy(pName);
	pC->show();
}

 

9.外观模式

是当一个系统很复杂时,系统提供给客户的是一个简单的对外接口,而把里面复杂的结构都封装了起来。客户只需使用这些简单接口就能使用这个系统,而不需要关注内部复杂的结构

案例:以播放器程序需要经过:解析器、解码器、显示

class cParser{
public:
	void start() {
		printf("start parser\n");
	}

	void stop() {
		printf("stop parser\n");
	}
};

class cDecoder{
public:
	void start() {
		printf("start decoder\n");
	}

	void stop() {
		printf("stop decoder\n");
	}
};

class cDisplay{
public:
	void start() {
		printf("start display\n");
	}

	void stop() {
		printf("stop display\n");
	}
};

class cPlayer {
public:
	cPlayer() {
		m_parser = new cParser();
		m_decoder = new cDecoder();
		m_display = new cDisplay();
	}

	~cPlayer() {
		if (m_parser != NULL) {
			delete m_parser;
		}

		if (m_decoder != NULL) {
			delete m_decoder;
		}

		if (m_display != NULL) {
			delete m_display;
		}
	}

	void start() {
		m_parser->start();
		m_decoder->start();
		m_display->start();
	}

	void stop() {
		m_parser->stop();
		m_decoder->stop();
		m_display->stop();
	}
private:
	cParser* m_parser;
	cDecoder* m_decoder;
	cDisplay* m_display;
};
int main()
{

	printf("测试9:外观模式\n");
	cPlayer* pP = new cPlayer();
	pP->start();
	pP->stop();
}

 

10.桥接模式

将抽象化与实现化解耦,使得二者可以独立变化

案例:像我们常用的JDBC桥DriverManager一样,JDBC进行连接数据库的时候,在各个数据库之间进行切换,基本不需要动太多的代码,甚至丝毫不用动,原因就是JDBC提供统一接口,每个数据库提供各自的实现,用一个叫做数据库驱动的程序来桥接就行了

class cDecoderH264 {
public:
	virtual void doDecode() = 0;
};

class cDecoderH264FromHW:public cDecoderH264 {
public:
	void doDecode() {
		printf("hw h264 decodering\n");
	}
};

class cDecoderH264FromSW :public cDecoderH264 {
public:
	void doDecode() {
		printf("sw h264 decodering\n");
	}
};

class cPlayerBridge {
public:
	virtual void createDecoder(cDecoderH264* decoder) = 0;
	virtual void doPlay() = 0;
protected:
	cDecoderH264 *pDecH264;
};

class cPlayerTencent :public cPlayerBridge {
public:
	void createDecoder(cDecoderH264* decoder) {
		pDecH264 = decoder;
	}

	void doPlay() {
		pDecH264->doDecode();
	}
};

class cPlayerYouku :public cPlayerBridge {
public:
	void createDecoder(cDecoderH264* decoder) {
		pDecH264 = decoder;
	}

	void doPlay() {
		pDecH264->doDecode();
	}
};
int main()
{
	printf("测试10:桥接模式\n");
	cDecoderH264 *p264 = new cDecoderH264FromHW();//
	cPlayerBridge *pPlayer = new cPlayerTencent();//
	pPlayer->createDecoder(p264);
	pPlayer->doPlay();
}

 

11.组合模式

将对象组合成树形结构以表示“部分-整体”的层次结构;
以树形结构表示“部分-整体”,那可以将组合模式想象成一根大树,将大树分成树枝和树叶两部分,树枝上可以再长树枝,也可以长树叶,树叶上则不能再长出别的东西

//Component抽象组件:为组合中所有对象提供一个接口,不管是叶子对象还是组合对象
class cComponent {  
protected:
	char* m_name;
public:
	cComponent(char* name) {
		m_name = name;
	}

	virtual ~cComponent() {

	}

	virtual void add(cComponent *pCom) {};    //虚函数
	virtual void remove(cComponent *pCom) {}; //虚函数

	virtual void display(int depth) = 0;   //纯虚函数
};

//Composite组合节点对象:实现了Component的所有操作,并且持有子节点对象
class cComposite :public cComponent {   
private:
	list <cComponent*> m_list;
public:
	cComposite(char* name) :cComponent(name) {

	}

	void add(cComponent *pCom) {
		m_list.push_front(pCom);
	}

	void remove(cComponent *pCom) {
		m_list.push_back(pCom);
	}

	void display(int depth) {
		printf("[cComposite][%s]name:%s,m_list:%d\n",__func__, m_name,m_list.size());

		list<cComponent *>::iterator iter = m_list.begin();
		for (; iter != m_list.end(); iter++) 
			(*iter)->display(depth + 2);
	}
};

//Leaf叶节点对象:叶节点对象没有任何子节点,实现了Component中的某些操作
class cLeaf : public cComponent {                                  
public:
	cLeaf(char* name) :cComponent(name) {

	}

	void display(int depth) {
		printf("[cLeaf][%s]depth:%d,name:%s\n",__func__,depth,m_name);
	}
};
int main()
{
        printf("测试11:组合模式\n");
	// 生成树根
	cComposite* pRoot = new cComposite((char*)"root");
	//为其增加两个叶子节点
	cLeaf* pLeafA1 = new cLeaf((char*)"Leaf A1 in Root");
	cLeaf* pLeafB1 = new cLeaf((char*)"Leaf B1 in Root");
	pRoot->add(pLeafA1);
	pRoot->add(pLeafB1);
	//为根增加两个枝节点
	cComposite* pBranchX = new cComposite((char*)"Branch X in Root");
	cComposite* pBranchY = new cComposite((char*)"Branch Y in Root");
	pRoot->add(pBranchX);
	pRoot->add(pBranchY);
	//为BranchX增加叶子节点
	cLeaf* pLeafA2 = new cLeaf((char*)"Leaf A2 in Branch X");
	pBranchX->add(pLeafA2);

	//显示树
	pRoot->display(1);
}

 

12.享元模式

运用共享技术有效地支持大量细粒度的对象。在有大量对象时,把其中共同的部分抽象出来,如果有相同的业务请求,直接返回内存中已有的对象,避免重新创建

案例:围棋只有两种颜色-黑白,如果我们把棋子作为一个抽象类Chess,黑棋BlackChess和白棋WhiteChess分别作为继承抽象类的具体类,那么每下一步都需要new一个新的棋子对象,如此下来会产生大量的黑白棋对象。
仔细观察黑白棋,不难发现黑白棋对象其实都一样,唯一不同的是其位置的变化。
那么有一种方法可以实现这样的效果:不用创建大量的黑白棋对象,但是也能准确的实现其位置的变化

const char* WHITE_CHESS = "white";
const char* BLACK_CHESS = "black";

//非享元(Unsharable Flyweight)角色:是不可以共享的外部状态,它以参数的形式注入具体享元的相关方法中
struct cChessPiecesPos {  //棋子位置
	int x;
	int y;

	cChessPiecesPos(int a,int b):x(a),y(b){}
};

//抽象享元角色(Flyweight):是所有的具体享元类的基类,为具体享元规范需要实现的公共接口,非享元的外部状态以参数的形式通过方法传入
class cChessPieces {                    //棋子
private:
	char* m_color;
public:
	cChessPieces(char* color) :m_color(color) {

	}

	virtual ~cChessPieces(){}

	virtual void draw(cChessPiecesPos* pPos) = 0;

	char* getColor() {
		return m_color;
	}
};

//具体享元(Concrete Flyweight)角色:实现抽象享元角色中所规定的接口
class cWhiteChessPieces:public cChessPieces {
public:
	cWhiteChessPieces(char* color) :cChessPieces(color) {
		printf("this is %s chesspieces\n", color);
	}

	~cWhiteChessPieces(){}

	void draw(cChessPiecesPos* pPos) {
		printf("color:%s is drawing at x:%d,y:%d\n", getColor(), pPos->x, pPos->y);
	}
};

class cBlackChessPieces :public cChessPieces {
public:
	cBlackChessPieces(char* color) :cChessPieces(color) {
		printf("this is %s chesspieces\n", color);
	}

	~cBlackChessPieces() {}

	void draw(cChessPiecesPos* pPos) {
		printf("color:%s is drawing at x:%d,y:%d\n", getColor(), pPos->x, pPos->y);
	}
};

//享元工厂(Flyweight Factory)角色:负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检査系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象。
class cChessPiecesBoard {     //棋盘
private:
	map<char*, cChessPieces*> m_chesspieces;
	static cChessPiecesBoard *m_cpb;
private:
	cChessPiecesBoard(){}
public:
	//单例模式
	static cChessPiecesBoard* getcChessPiecesBoardIns() {
		if (m_cpb == NULL) {
			m_cpb = new cChessPiecesBoard();
		}
		return m_cpb;
	}

	cChessPieces* getChessPieces(char* color) {
		map<char*, cChessPieces*>::iterator iter1 = m_chesspieces.find(color);

		if (iter1 == m_chesspieces.end()) {
			if (!strcmp(color, WHITE_CHESS)) {
				m_chesspieces.insert(pair<char*, cChessPieces*>(color, new cWhiteChessPieces(color)));
			}
			else if (!strcmp(color, BLACK_CHESS)) {
				m_chesspieces.insert(pair<char*, cChessPieces*>(color,new cBlackChessPieces(color)));
			}
		}
		map<char*, cChessPieces*>::iterator iter2 = m_chesspieces.find(color);
		return (cChessPieces*)iter2->second;
	}
};

cChessPiecesBoard * cChessPiecesBoard::m_cpb = NULL;  //静态变量初始化,否则编译error LNK2001: 无法解析的外部符号 "private: static class
int main()
{
	printf("测试12:享元模式\n");
	cChessPiecesBoard *pCPB = cChessPiecesBoard::getcChessPiecesBoardIns();
	cChessPieces* pWCP = pCPB->getChessPieces((char*)WHITE_CHESS);
	cChessPieces* pBCP = pCPB->getChessPieces((char*)BLACK_CHESS);
	int whitePosX = 5;//
	int whitePosY = 6;//
	pWCP->draw(new cChessPiecesPos(whitePosX, whitePosY));
	int blackPosX = 6;//
	int blackPosY = 5;//
	pBCP->draw(new cChessPiecesPos(blackPosX, blackPosY));
}

 

三.行为型模式(11种)

13.策略模式

定义一系列的算法,把它们一个个封装起来,并且使它们可相互替;也就是说这些算法所完成的功能一样,对外的接口一样,只是各自实现上存在差异

//在策略模式中,参数的传递难以避免,客户必须指定某种算法
class cEncoder {
public:
	virtual void doEncoder() = 0;
};

//两种具体的编码器
class cHEVCEncoder :public cEncoder {
public:
	void doEncoder() {
		printf("Using hevc encoder to ...\n");
	}
};

class cAVCEncoder : public cEncoder {
public:
	void doEncoder() {
		printf("Using sw encoder to ...\n");
	}
};

//录像1:直接通过参数指定,传入一个特定算法的指针
//用这种方式,客户就需要知道这些算法的具体定义
class cRecoder1 {
public:
	cRecoder1(cEncoder *pEncoder) {
		m_pEnc = pEncoder;
	}

	void doRecoder() {
		m_pEnc->doEncoder();
	}
private:
	cEncoder *m_pEnc;
};

//录像2:也是直接通过参数指定,只不过不是传入指针,而是一个标签
//这样客户只要知道算法的相应标签即可,而不需要知道算法的具体定义
enum ENCODER_TYPE{T_HEVC,T_AVC};
class cRecoder2 {
public:
	cRecoder2(ENCODER_TYPE type) {
		if (type == T_HEVC) {
			m_pEnc = new cHEVCEncoder();
		}else if (type == T_AVC) {
			m_pEnc = new cAVCEncoder();
		}
	}

	void doRecoder() {
		m_pEnc->doEncoder();
	}
private:
	cEncoder *m_pEnc;
};

//录像3:模板实现。算法通过模板的实参指定
//还是使用了参数,只不过不是构造函数的参数
template <class Encoder>
class Recoder3 {
public:
	void doRecoder() {
		m_Enc.doEncoder();
	}
private:
	Encoder m_Enc;
};
int main()
{
	printf("测试13:策略模式\n");
	cEncoder *pc = new cHEVCEncoder();//
	cRecoder1 cr1(pc);
	cr1.doRecoder();

	ENCODER_TYPE typ = T_AVC;//
	cRecoder2 cr2(typ);
	cr2.doRecoder();

	Recoder3<cHEVCEncoder> cr3;//
	cr3.doRecoder();
}

 

14.模板模式

用模板方法模式:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤

class cPhone {
public:
	void produce() {
		installCPU();
		installRAM();
		intstallChipset();
	}

protected:
	virtual void installCPU() = 0;
	virtual void installRAM() = 0;
	virtual void intstallChipset() = 0;
};

class cPhoneH:public cPhone{
protected:
	void installCPU() {
		printf("Phone High has 8 core cpu\n");
	}

	void installRAM() {
		printf("Phone High has 4G ram\n");
	}
	
	void intstallChipset() {
		printf("Phone High has msm8998 chopset\n");
	}
};

class cPhoneL :public cPhone {
protected:
	void installCPU() {
		printf("Phone Low has 4 core cpu\n");
	}

	void installRAM() {
		printf("Phone High has 2G ram\n");
	}

	void intstallChipset() {
		printf("Phone High has msm8996 chopset\n");
	}
};
int main()
{
	printf("测试14:模板模式\n");
	cPhone *pPhone = NULL;
	pPhone = new cPhoneL();//
	pPhone->produce();
}

 

15.观察者模式

16.迭代子模式

17.责任链模式

18.命令模式

19.备忘录模式

20.状态模式

21.访问者模式

22.中介者模式

23.解释器模式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值