目录
一. 用于创建对象的设计模式
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---------------