目录
设计模式为先辈总结的经验性结构,具有良好的代码复用性。。。
单例模式
单例模式属于创建型模式,有三种要点:
- 当前类最多只能创建一个实例。
- 它必须 自己创建这个实例,不能让调用者创建。
- 它必须自己向整个系统提供全局访问点访问这个实例。
单例模式的优点:
- 提供了严格的对唯一实例的创建、访问和销毁,安全性高。
- 单例模式的实现可以节省系统资源。
单例模式-懒汉式
懒汉式:现用现创建,用创建的时间节省其他不需要它时候的空间。
写法一:
class CSingleton {
private:
CSingleton() {}
CSingleton(const CSingleton&) = delete; //ban掉拷贝防止创建第二个单例。
static CSingleton* p_sin; //与get函数同步采用静态
~CSingleton() {} //析构私有,防止随意删除
static class delsingleton { //最后的保底手段,定义一个类内类利用其析构在生命周期结束时自动回收单例。
public:
~delsingleton() {
if (p_sin) {
delete p_sin;
p_sin = nullptr;
}
}
} delsin;
public:
static CSingleton* GetSingleton() { //为了保证调用时对象存在,采用静态
if (!p_sin) { //空指针则调用构造
p_sin = new CSingleton();
}
return p_sin;
}
static void DeleteSingleton(CSingleton*& pnow) { //删除也要 类内自己删除,不能让其直接调用析构。
if (p_sin) {
delete p_sin;
p_sin = nullptr;
pnow = nullptr;
}
}
};
CSingleton* CSingleton::p_sin = nullptr; //静态初始化
CSingleton::delsingleton CSingleton::delsin;
遗留问题:在单线程模式下可以保证功能,多线程下仍有可能创建多个对象。需采用线程同步。
写法二:
class CSingleton {
private:
CSingleton() {}
CSingleton(const CSingleton&) = delete;
~CSingleton() {}
public:
static CSingleton* GetSingleton() {
static CSingleton sin; //定义为静态,保证全局只创建一次,并且伴随程序结束自动回收。
return &sin;
}
};
写法二不存在和写法一一样的遗留问题,由系统保证只会创建一个。
对比:写法一虽然繁琐,但是可以做到随时删除,节省空间。写法二简洁,但删除相对死板。
单例模式-饿汉式
饿汉式:在程序运行前就将单例模式准备好。
class CSingleton {
private:
CSingleton() {}
CSingleton(const CSingleton&) = delete;
~CSingleton() {}
static CSingleton sin; // 直接在程序运行开始定义好,随时使用,由系统自动回收。
public:
static CSingleton* GetSingleton() {
return &sin;
}
};
CSingleton CSingleton::sin;
缺陷:发生在跨文件使用时的一种问题,有概率在单例模式被创建好前就由其他文件使用这个单例,导致不能正确获取单例。
例如:有四个文件A.h A.cpp B.cpp C.cpp,在A.h中定义单例模式,在C中初始化静态变量sin而在A、B、C中都使用单例模式创造变量。在生成顺序为A.cpp B.cpp C.cpp的情况下,A、B中的单例将不会有正确的值。
工厂模式
工厂模式-简单工厂
class CEngine {
public:
virtual void work() = 0;
};
class CEngine2L : public CEngine {
public:
void work() {
cout << "自然吸气 嗡嗡嗡\n";
}
};
class CEngine2T : public CEngine {
public:
void work() {
cout << "涡轮增压 嗡嗡嗡\n";
}
};
class CFactory {
public:
CEngine* CreateEngine(const string& type) {
if (type == "2.0L") {
return new CEngine2L;
}
else if (type == "2.0T") {
return new CEngine2T;
}
return nullptr;
}
};
class CCar {
public:
CEngine* p_eng;
CCar(const string& type) {
if (type == "2.0L") {
p_eng = new CEngine2L;
}
else if (type == "2.0T") {
p_eng = new CEngine2T;
}
else p_eng = nullptr;
}
//为何要引入简单工厂 ?解决 耦合 的问题。
CCar(CFactory* pfac, const string& type)
:p_eng(pfac ? pfac->CreateEngine(type) : nullptr) {
}
~CCar() {
if (p_eng) {
delete p_eng;
p_eng = nullptr;
}
}
public:
void drive() {
if (p_eng) {
p_eng->work();
cout << "小汽车 呜呜开\n";
}
}
};
工厂模式-工厂方法
将工厂类内的创造函数定义为虚函数,并为每个零件定义子类继承工厂类。
class CFactoryEngine {
public:
virtual CEngine* CreateEngine() = 0; //在这里使用虚函数
};
class CFac2L :public CFactoryEngine { //定义子类
public:
CEngine* CreateEngine() {
return new CEngine2L;
}
};
class CFac2T :public CFactoryEngine {
public:
CEngine* CreateEngine() {
return new CEngine2T;
}
};
使用时直接传入子类指针进行赋值。
CCar(CFactoryEngine* pfac) :p_eng(pfac ? pfac->CreateEngine() : nullptr) {}
CFac2L fac2L;
CFac2T fac2T;
CCar car(&fac2L);
car.drive();
好处:解决耦合,对修改关闭,对扩展开放,增加新零件时只需要继续扩展子类,而无需对工厂类内的代码进行更正。
工厂模式-抽象工厂
抽象工厂解决了工厂模式中类过多的问题,将产品合并形成合并的子类并进行创建,但实际应用中还需要考虑应用场景选择合适的工厂种类。
class CEngine {
public:
virtual void work() = 0;
};
class CEngine2L : public CEngine {
public:
void work() {
cout << "自然吸气 嗡嗡嗡\n";
}
};
class CEngine2T : public CEngine {
public:
void work() {
cout << "涡轮增压 嗡嗡嗡\n";
}
};
class CGearBox {
public:
virtual void work() = 0;
};
class CGearBoxManual :public CGearBox {
public:
void work() {
cout << "手动挡变速箱工作ing\n";
}
};
class CGearBoxAuto :public CGearBox {
public:
void work() {
cout << "自动挡变速箱工作ing\n";
}
};
class CFactory { //引入总体工厂
public:
virtual CEngine* CreateEngine() = 0;
virtual CGearBox* CreateGearBox() = 0;
};
class CFac2TManual :public CFactory { //总体工厂的子类为所需要的产品型号的合并类型
public:
CEngine* CreateEngine() {
return new CEngine2T;
}
CGearBox* CreateGearBox() {
return new CGearBoxManual;
}
};
class CCar {
public:
CEngine* p_eng;
CGearBox* p_gear;
//引入抽象工厂
CCar(CFactory* pfac) :
p_eng(pfac ? pfac->CreateEngine() : nullptr),
p_gear(pfac ? pfac->CreateGearBox() : nullptr) {
}
~CCar() {
if (p_eng) {
delete p_eng;
p_eng = nullptr;
}
if (p_gear) {
delete p_gear;
p_gear = nullptr;
}
}
public:
void drive() {
if (p_eng && p_gear) {
p_eng->work();
p_gear->work();
cout << "小汽车 呜呜开\n";
}
}
};