常见设计模式

一. 用于创建对象的设计模式1. 工厂模式 (1) 说明:需要生产大量对象,且对象具有多态特性。 (2) 类图结构 (3) 工厂模式分为"简单工厂"和"抽象工厂",这里说一下抽象工厂,eg, 要生产不同品牌的电池,简单工厂就能解决,如果还要生产不同品牌的主板呢?那么就需要再增加一个工厂类来生产,抽象工厂类就是这么来的。 (4) 实际工程中,工...
摘要由CSDN通过智能技术生成

目录

一. 用于创建对象的设计模式

        1. 工厂模式

        2.  建造者模式

        3. 原型模式

        4. 单例模式 

二. 类与对象之间的组合

        1. 适配器模式

         2. 桥接模式 

        3. 组合模式

        4. 装饰模式

        5. 享元模式

        6. 代理模式

三. 对象间通信 

        1. 职责链模式

        2. 中介者模式 

        3.  备忘录模式

        4.  观察者模式

        5.  策略模式

        6. 模板模式 

        7. 外观模式 


一. 用于创建对象的设计模式

        1. 工厂模式

                (1) 说明:需要生产大量对象,且对象具有多态特性。

                (2) 类图结构

                 (3)  工厂模式分为"简单工厂"和"抽象工厂",这里说一下抽象工厂,eg, 要生产不同品牌的电池,简单工厂就能解决,如果还要生产不同品牌的主板呢?那么就需要再增加一个工厂类来生产,抽象工厂类就是这么来的。

                 (4)  实际工程中,工厂模式一般都是配合别的设计模式(模板模式,建造者模式等)搭配使用的,每需要增加一个产品,就需要增加一个产品类,其实是不符合“开闭原则”的,且会在业务层new出来很多对象,不方便管理。下面例子将产品类对象交给工厂类(这里使用了单例模式,后面会讲到)管理,业务逻辑则放到业务模块,这样每增加一个产品类,就只需要在工厂类注册一下就好了,类对象的释放由工厂类管理。

#pragma once
#include <vector>

//产品抽象类
class IProduct
{
public:
	virtual void Run() = 0;
};

//产品A实例
class CProductA : public IProduct
{
public:
	virtual void Run() override;
};

//产品B实例
class CProductB : public IProduct
{
public:
	virtual void Run() override;
};


//工厂类
class CFactory
{
public:
	CFactory();
	CFactory(const CFactory&) = delete;
	CFactory& operator=(const CFactory&) = delete;
	~CFactory();

private:
	void RegisterProduct(IProduct* pProduct);
	void UnRegisterProducts();

public:
	static CFactory& GetInstance(); 
	std::vector<IProduct*>& GetProductsVec();

private:
	std::vector<IProduct*> m_vecProducts;
};
#include "stdafx.h"
#include "Factory.h"

void CProductA::Run()
{
	printf("productA: run()\n");
}

void CProductB::Run()
{
	printf("productB: run()\n");
}


CFactory::CFactory()
{
	RegisterProduct(new CProductA);
	RegisterProduct(new CProductB);
}


CFactory::~CFactory()
{
	UnRegisterProducts();
}

void CFactory::RegisterProduct(IProduct* pProduct)
{
	if (nullptr == pProduct) return;

	if (m_vecProducts.end() == std::find(m_vecProducts.begin(), m_vecProducts.end(), pProduct))
	{
		m_vecProducts.push_back(pProduct);
	}
}

void CFactory::UnRegisterProducts()
{
	for (auto atProduct : m_vecProducts)
	{
		if (nullptr != atProduct) delete atProduct;
	}
}

CFactory& CFactory::GetInstance()
{
	static CFactory s_objFactory; 
	return s_objFactory; 
}

std::vector<IProduct*>& CFactory::GetProductsVec()
{
	return m_vecProducts;
}
	//业务逻辑放在业务处理模块中
	auto atVecFactory = CFactory::GetInstance().GetProductsVec();
	for (auto atProduct : atVecFactory)
	{
		atProduct->Run();
	}

        2.  建造者模式

                (1) 说明:将一个复杂对象的构建与它的表示分离,使同样的构建过程生成不同的表示。eg, 玩具厂要生产不同类型奥特曼,生产过程都是生产头,身体,手,脚,但是生产细节是不一样的,比如生产头,就有赛罗,迪迦等,那么套用建造者模式,就可以使用相同的生产过程,生产不同类型的奥特曼了。

                (2) 类结构图

                (3) 建造者模式和模板模式是不是有点像的感觉,奥特曼的例子用模板模式同样也能实现,后面讲到模板模式,我们再讲讲区别。

                (4) 建造者模式的CDirector类用来管理builder对象和生产过程,builder对象通过构造函数传入,builder生产过程由build()实现,同时也管理builder对象的释放,所以在业务层,我们只管构造生产对象和启动生产过程。

#pragma once
#include <vector>
//建造抽象类
class IBuilder
{
public:
	virtual ~IBuilder() = default;

	virtual void BuildHeader() = 0;
	virtual void BuildBody() = 0;
	virtual void BuildFeet() = 0;
};

//建造实例:peson
class CPesonBuilder : public IBuilder
{
	virtual ~CPesonBuilder() = default;

	virtual void BuildHeader() override;
	virtual void BuildBody() override;
	virtual void BuildFeet() override;
};

//建造实例:group
class CGroupBuilder : public IBuilder
{
	virtual ~CGroupBuilder() = default;

	virtual void BuildHeader() override;
	virtual void BuildBody() override;
	virtual void BuildFeet() override;
};


//建造管理类
class CDirector
{
public:
	//explicit CDirector(IBuilder* pobjBuilder);//防止隐式转换
	virtual ~CDirector();

	void CreateBuilder(IBuilder* pobjBuilder);
	void Build();
private:
	std::vector<IBuilder*> m_vecBuilders;
};
#include "stdafx.h"
#include "Builder.h"


void CPesonBuilder::BuildHeader()
{
	printf("pesonBuilder: buildHeader\n");
}

void CPesonBuilder::BuildBody()
{
	printf("pesonBuiler: buildBody\n");
}

void CPesonBuilder::BuildFeet()
{
	printf("pesonBuilder: buildFeet\n");
}

void CGroupBuilder::BuildHeader()
{
	printf("GroupBuilder: buildHeader\n");
}

void CGroupBuilder::BuildBody()
{
	printf("GroupBuiler: buildBody\n");
}

void CGroupBuilder::BuildFeet()
{
	printf("GroupBuilder: buildFeet\n");
}


CDirector::~CDirector()
{
	for (auto atBuilder : m_vecBuilders)
	{
		if (atBuilder) delete atBuilder;
	}
}

void CDirector::CreateBuilder(IBuilder* pobjBuilder)
{
	if (nullptr == pobjBuilder) return;

	if (m_vecBuilders.end() == std::find(m_vecBuilders.begin(), m_vecBuilders.end(), pobjBuilder))
	{
		m_vecBuilders.push_back(pobjBuilder);
	}
}

void CDirector::Build()
{
	for (auto atBuilder : m_vecBuilders)
	{
		atBuilder->BuildHeader();
		atBuilder->BuildBody();
		atBuilder->BuildFeet();
	}
}
	//业务层负责构建对象和开启生产过程
	CDirector* pDirector = new CDirector;
	pDirector->CreateBuilder(new CPesonBuilder);
	pDirector->CreateBuilder(new CGroupBuilder);
	pDirector->Build();

	if (pDirector) delete pDirector;

        3. 原型模式

                (1)  说明: 原型模式本质就是实现深拷贝。

                (2) 补补课:浅拷贝就是值传递,共享内存块。默认拷贝构造函数为浅拷贝,下面例子能很好地说明,如果析构里释放m_pcName,就会报错,原因是同一块内存释放两次。

class CTest
{
public:
	CTest();
	void SetName(LPCTSTR lpName);
	void Show();
private:
	TCHAR* m_pcName;
};
CTest::CTest()
{
	m_pcName = new TCHAR[200];
}

void CTest::SetName(LPCTSTR lpName)
{
	_tcscpy_s(m_pcName, 200, lpName);
}

void CTest::Show()
{
	_tprintf(m_pcName);
}
	CTest objTest;
	objTest.SetName(_T("niuiuiuiu\n"));
	CTest objTest1 = objTest;
	objTest.Show();
	objTest1.Show();

	objTest1.SetName(_T("ttttttttttttttttttttt\n"));
	objTest1.Show();
	objTest.Show();

                 (3) 深拷贝会重新创建一个内存块,有独立的寻址空间。

class CTest
{
public:
	CTest();
	CTest(const CTest&);//拷贝构造函数
	void SetName(LPCTSTR lpName);
	void Show();
private:
	TCHAR* m_pcName;
};
CTest::CTest()
{
	m_pcName = new TCHAR[200];
	_tcscpy_s(m_pcName, 200, _T("initvalue\n"));
}

CTest::CTest(const CTest&)
{
	m_pcName = new TCHAR[200];
	_tcscpy_s(m_pcName, 200, _T("initvalue\n"));
}


void CTest::SetName(LPCTSTR lpName)
{
	_tcscpy_s(m_pcName, 200, lpName);
}

void CTest::Show()
{
	_tprintf(m_pcName);
}
	CTest objTest;
	objTest.SetName(_T("niuiuiuiu\n"));
	CTest objTest1 = objTest;
	objTest.Show();
	objTest1.Show();

	objTest1.SetName(_T("ttttttttttttttttttttt\n"));
	objTest1.Show();
	objTest.Show();

                 (4) 下面我们就来看看原型模式的例子

#pragma once
#include <wtypes.h>

class IPrototype
{
public:
	IPrototype() = default;
	IPrototype(const IPrototype&) = default;
	virtual ~IPrototype() = default;

	virtual IPrototype* Clone() = 0;
	virtual void Show() = 0;

protected:
	TCHAR* m_pcName;
};

class CPrototype : public IPrototype
{
public:
	CPrototype();
	CPrototype(const CPrototype&);
	virtual ~CPrototype() = default;

	virtual IPrototype* Clone() override;
	virtual void Show() override;

	void SetName(LPCTSTR lpName);
};
#include "stdafx.h"
#include "Prototype.h"

CPrototype::CPrototype()
{
	m_pcName = new TCHAR[MAX_PATH];
	_tcscpy_s(m_pcName, MAX_PATH, _T("init prototype\n"));
}

CPrototype::CPrototype(const CPrototype&)
{
	m_pcName = new TCHAR[MAX_PATH];
	_tcscpy_s(m_pcName, MAX_PATH, _T("init prototype\n"));
}

IPrototype* CPrototype::Clone()
{
	return new CPrototype(*this);
}

void CPrototype::Show()
{
	_tprintf(m_pcName);
}

void CPrototype::SetName(LPCTSTR lpName)
{
	_tcscpy_s(m_pcName, MAX_PATH, lpName);
}
	//业务层负责对象的拷贝
	CPrototype* pPrototype = new CPrototype;
	CPrototype* pCloneProto = (CPrototype*)pPrototype->Clone();
	pCloneProto->SetName(_T("clone prototype\n"));
	pPrototype->Show();
	pCloneProto->Show();

	if (pPrototype) delete pPrototype;
	if (pCloneProto) delete pCloneProto;

        4. 单例模式 

                (1) 说明:在程序生命周期只有一个实例,很适合在日志操作对象类中使用。

                (2) 类结构图

                (3) 普通懒汉模式(线程安全):需要时创建对象,双检锁机制是为了减少加锁的开销。

                       先看看不加锁的效果:明显与单例模式的定义不符

                      下面是加锁的效果:

#pragma once
#include <future>

class CSingle
{
public:
	CSingle();
	CSingle(const CSingle&) = delete;
	CSingle& operator=(const CSingle&) = delete;
	~CSingle();

	static CSingle* GetInstance();
	void Run();
	void Destroy();
private:
	static std::mutex sm_objMutex;
	static CSingle* sm_pobjSingle;
};


class CThread
{
public:
	CThread();
	virtual ~CThread();

	void DoThread();
private:
	std::future<void> m_fuThread;
};
#include "stdafx.h"
#include "Single.h"

CSingle::CSingle()
{
	printf("CSingle------------------\n");
}

CSingle::~CSingle()
{
	printf("~CSingle------------------\n");
}

std::mutex CSingle::sm_objMutex;
CSingle* CSingle::sm_pobjSingle = nullptr;
CSingle* CSingle::GetInstance()
{
	//static CSingle s_objSingle;
	//return s_objSingle;

	if (nullptr == sm_pobjSingle)
	{
		sm_objMutex.lock();
		if (nullptr == sm_pobjSingle)
		{
			CSingle* pSingle = new CSingle;
			sm_pobjSingle = pSingle;
		}
		sm_objMutex.unlock();
	}
	return sm_pobjSingle;
}

void CSingle::Run()
{
	printf("Single address: %p\n", this);
}

void CSingle::Destroy()
{
	if (sm_pobjSingle)
	{
		sm_objMutex.lock();
		delete sm_pobjSingle;
		sm_pobjSingle = nullptr;
		sm_objMutex.unlock();
	}
}

CThread::CThread()
{
	m_fuThread = std::async(std::launch::async, &CThread::DoThread, this);
}

CThread::~CThread()
{
	m_fuThread.get();
}

void CThread::DoThread()
{
	CSingle::GetInstance()->Run();
}
	CThread* paThread[10] = { 0 };
	for (int i = 0; i < 10; i++)
	{
		paThread[i] = new CThread;
	}
	Sleep(2000);
	for (int i = 0; i < 10; i++)
	{
		delete paThread[i];
	}
	CSingle::GetInstance()->Destroy();

                 (4) 静态局部变量的懒汉模式:C++0X以后,要求编译器保证内部静态变量的线程安全性,可以不加锁,使用起来很方便。

#pragma once
#include <future>

class CSingle
{
public:
	CSingle();
	CSingle(const CSingle&) = delete;
	CSingle& operator=(const CSingle&) = delete;
	~CSingle();

	static CSingle& GetInstance();
	void Run();
};


class CThread
{
public:
	CThread();
	virtual ~CThread();

	void DoThread();
private:
	std::future<void> m_fuThread;
};
#include "stdafx.h"
#include "Single.h"

CSingle::CSingle()
{
	printf("CSingle------------------\n");
}

CSingle::~CSingle()
{
	printf("~CSingle---------------
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值