常用设计模式
单例模式
定义:一个类不管创建多少次对象,永远只能得到该类型一个对象的实例,常用到的如,日志模块,数据库模块
分类:
- 饿汉式单例模式:还没有获取实例对象,实例对象就已经产生了
- 懒汉式单例模式:唯一的实例对象直到第一次获取时才创建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| class Singleton { public: static Singleton * getInstance() { return &instance; }
private: static Singleton instance;
Singleton() { }
Singleton(const Singleton& ) = delete; Singleton& operator=(const Singleton&) = delete; };
Singleton Singleton::instance;
|
单例的饿汉实现是线程安全的,因为对象在使用前就已经创建出来了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| class Singleton { public: static Singleton * getInstance() { if(instance == nullptr) { instance = new Singleton(); } return instance; }
private: static Singleton* instance;
Singleton() { }
Singleton(const Singleton& ) = delete; Singleton& operator=(const Singleton&) = delete; };
Singleton* Singleton::instance = nullptr;
|
上述懒汉式单例模式并非线程安全,getInstance函数并非可重入函数。若要改为线程安全的懒汉式单例模式只需修改getInstance函数
1 2 3 4 5 6 7 8 9 10 11
| static Singleton * getInstance() { if(instance == nullptr) { std::lock_guard<std::mutex> guard(mtx); if(instance == nullptr) { instance = new Singleton(); } } return instance; } static Singleton* volatile instance;
|
全局变量、文件域的静态变量和类的静态成员变量在main执行之前的静态初始化过程中分配内存并初始化;局部静态变量(一般为函数内的静态变量)在第一次使用时分配内存并初始化。这里的变量包含内置数据类型和自定义类型的对象。
非局部静态变量一般在main执行之前的静态初始化过程中分配内存并初始化,可以认为是线程安全的;
局部静态变量在编译时,在g++中通过查看汇编指令发现已经添加了线程互斥操作,故是线程安全的
故懒汉式单例模式也可以改写为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class Singleton { public: static Singleton * getInstance() { static Singleton instance; return &instance; } private: static Singleton* volatile instance; Singleton() { } Singleton(const Singleton& ) = delete; Singleton& operator=(const Singleton&) = delete; };
|
工厂模式
定义:
这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。简单来说,使用了C++多态的特性,将存在继承关系的类,通过一个工厂类创建对应的子类(派生类)对象。在项目复杂的情况下,可以便于子类对象的创建。
分类:
- 简单工厂:simple factory
- 工厂方法:factory method
- 抽象工厂:abstract factory
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| class Car { public: explicit Car(string name) : _name(std::move(name)) {} virtual void show() = 0; protected: string _name; };
class BMW : public Car { public: explicit BMW(string name) : Car(std::move(name)) {}
void show() override { cout << "获取BMW" << _name << endl; } };
class Audi : public Car { public: explicit Audi(string name) : Car(std::move(name)) {} void show() override { cout << "获取AUdi" << _name << endl; } };
enum class CarType { BMW, AUDI };
class SimpalFactory { public: Car *createCar(CarType ct) { switch (ct) { case CarType::BMW: return new BMW("X1"); break; case CarType::AUDI: return new Audi("A6"); default: cerr << "Usage argv is not right" << endl; } } };
int main() {
unique_ptr<SimpalFactory> factory(new SimpalFactory()); unique_ptr<Car> p1(factory->createCar(CarType::BMW)); }
|
简单工厂模式在扩展时要修改许多东西,当通过多态增加一种汽车时,工厂类对应的枚举值要增加,要修改工厂类中createCar函数。比较麻烦不符合对扩展关闭的原则,改进为工厂方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| class Car { public: explicit Car(string name) : _name(std::move(name)) {} virtual void show() = 0; protected: string _name; }; class BMW : public Car { public: explicit BMW(string name) : Car(std::move(name)) {} void show() override { cout << "获取BMW" << _name << endl; } }; class Audi : public Car { public: explicit Audi(string name) : Car(std::move(name)) {} void show() override { cout << "获取AUdi" << _name << endl; } }; class Factory { public: virtual Car *createCar(string name) = 0; }; class BMWFactory : public Factory { public: Car *createCar(string name) override { return new BMW(name); } }; class AudiFactory : public Factory { public: Car * createCar(string name) override { return new Audi(name); } }; int main() { unique_ptr<Factory> bmwfty(new BMWFactory()); unique_ptr<Factory> audifty(new AudiFactory()); unique_ptr<Car> p1(bmwfty->createCar("X6")); unique_ptr<Car> p2(audifty->createCar("A6")); p1->show(); p2->show(); return 0; }
|
对于工厂方法,当扩展时,只需继承Car通过多态实现实体后,继承Factory通过多态实现createCar。
但是实际情况并非如此,一个工厂可能及生产手机又生产耳机或者生产音响,对于工厂方法来说,每个工厂只能生产一个物品,当物品多且相似时这种设计是不好的,因此产生了抽象工厂
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
| class Car { public: explicit Car(string name) : _name(std::move(name)) {} virtual void show() = 0; protected: string _name; }; class BMW : public Car { public: explicit BMW(string name) : Car(std::move(name)) {}
void show() override { cout << "获取BMW" << _name << endl; } }; class Audi : public Car { public: explicit Audi(string name) : Car(std::move(name)) {}
void show() override { cout << "获取AUdi" << _name << endl; } }; class Light { public: virtual void show() = 0; }; class bmwLight : public Light { public: void show() override { cout << "BMW light" << endl; } }; class audiLight : public Light { public: void show() override { cout << "Audi light" << endl; } };
class AbstractFactory { public: virtual Car *createCar(string name) = 0; virtual Light *createCarLight() = 0; }; class BMWFactory : public AbstractFactory { public: Car *createCar(string name) override { return new BMW(name); } Light *createCarLight() override { return new bmwLight; } }; class AudiFactory : public AbstractFactory { public: Car *createCar(string name) override { return new Audi(name); } Light *createCarLight() override { return new audiLight; } }; int main() { unique_ptr<AbstractFactory> bmwfty(new BMWFactory); unique_ptr<AbstractFactory> Audifty(new AudiFactory); unique_ptr<Car> p1(bmwfty->createCar("x1")); unique_ptr<Car> p2(Audifty->createCar("A6")); unique_ptr<Light> p3(bmwfty->createCarLight()); unique_ptr<Light> p4(Audifty->createCarLight()); p1->show();p2->show();p3->show();p4->show(); return 0; }
|
但是抽象工厂也存在一些问题,当bmw工厂存在特殊的方法(其他工厂没有时),此时需要在Abstractory基类中添加纯虚函数,但是只有bmw工厂给出了具体的实现,其他工厂必须重写否则无法通过编译,一般实现为空
简单工厂把对象的创建封装在一个接口函数里面,通过传入不同的标志,返回创建的对象,客户不用自己new对象,不用了解对象创建的细节
工厂方法Factory基类提供了一个纯虚函数(创造产品),定义派生类(具体产品的工厂)负责创建对应的产品,可以做到不同的产品在不同的工厂里创建
抽象工厂把有关联的属于一个产品族的所有产品创建接口函数,放在一个抽象工厂中,派生类(具体产品的工厂)应该负责创建该产品族里的所有产品
代理模式
通过代理类来控制实际对象的访问权限
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| class VideoSite { public: virtual void freeMovie() = 0; virtual void vipMovie() = 0; virtual void ticketMovie() = 0; };
class FixbugVideoSite : public VideoSite { public: virtual void freeMovie() { cout << "freeMovie" << endl; }
virtual void vipMovie() { cout << "vipMovie" << endl; }
virtual void ticketMovie() { cout << "ticketMovie" << endl; } };
class FreeVideoSiteProxy : public VideoSite { public: FreeVideoSiteProxy() { pVideo = new FixbugVideoSite; } ~FreeVideoSiteProxy() { delete pVideo; }
virtual void freeMovie(){ pVideo->freeMovie(); } virtual void vipMovie() { cout<<"vip视频,您无权访问"<<endl; } virtual void ticketMovie(){ cout<<"需要买卷"<<endl; } private: VideoSite *pVideo; };
class vipVideoSiteProxy : public VideoSite{ public: vipVideoSiteProxy(){ p = new FixbugVideoSite ;} ~vipVideoSiteProxy() { delete p; }
virtual void freeMovie(){ p->freeMovie(); } virtual void vipMovie() { p->vipMovie(); } virtual void ticketMovie(){ cout<<"需要买卷"<<endl; } private: VideoSite* p; };
void watchMovie(unique_ptr<VideoSite> & ptr){ ptr->freeMovie(); ptr->vipMovie(); ptr->ticketMovie(); }
int main() {
unique_ptr<VideoSite> p1(new FreeVideoSiteProxy); unique_ptr<VideoSite> p2(new vipVideoSiteProxy); watchMovie(p1); watchMovie(p2); }
|
装饰器模式
装饰器模式是为了增加现有类的功能。但是增加现有类功能的另一个方法是增加一个子类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| class Car { public: virtual void show() = 0; };
class BMW : public Car { public: void show() { cout << "这是一个BMW汽车,配置有:基本配置" << endl; } };
class Audi : public Car { public: void show() { cout << "这是一个Audi汽车,配置有:基本配置" << endl; } };
class Benz : public Car { public: void show() { cout << "这是一个Benz汽车,配置有:基本配置" << endl; } };
class ConcreteDecorator01 : public Car { public: ConcreteDecorator01(Car* p) : pCar(p) {} void show() { pCar->show(); cout<<"新增方法01"<<endl; } private: Car* pCar; };
class ConcreteDecorator02 : public Car { public: ConcreteDecorator02(Car* p) : pCar(p) {} void show() { pCar->show(); cout<<"新增方法02"<<endl; }
private: Car * pCar; };
int main() { Car * p1 = new ConcreteDecorator01(new BMW()); p1->show(); Car * p2 = new ConcreteDecorator01(new ConcreteDecorator02(new BMW)); p2->show(); }
|
适配器模式
让不兼容的接口可以在一起工作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| class VGA { public: virtual void play() = 0; std::string getType() { return "VGA"; } };
class TV01 : public VGA { public: void play() { cout << "通过VGA 接口连接投影 并播放" << endl; } };
class Computer { public: void PlayVideo(VGA *pVGA) { pVGA->play(); } };
class HDMI { public: virtual void play() = 0; };
class TV02 : public HDMI { public: void play() override { cout << "通过HDMI 接口连接投影 并播放" << endl; } };
class VGA2HDMI : public VGA { public: VGA2HDMI(HDMI *p) : pHDMI(p) {}
void play() override { pHDMI->play(); }
private: HDMI *pHDMI; };
int main() { Computer c; c.PlayVideo(new TV01); c.PlayVideo(new VGA2HDMI(new TV02())); }
|
观察者模式
主要关注的是对象的一对多关系,也就是多个对象都依赖一个对象,当该对象的状态发生改变时,其他对象都能接受到相应的通知
如:我们有一组数据,可以通过这组数据生成对应的曲线图,柱状图,圆饼图。当数据改变时,这三个图都要发生变化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
| class Observer { public: virtual void handle(int msgid) = 0; };
class Observer1 : public Observer { public: void handle(int msgid) { switch (msgid) { case 1: cout << "Observer1 recv 1 msg!" << endl; break; case 2: cout << "Observer1 recv 2 msg!" << endl; break; default: cout << "Observer1 recv unknow msg!" << endl; break; } } };
class Observer2 : public Observer { public: void handle(int msgid) { switch (msgid) { case 2: cout << "Observer2 recv 2 msg!" << endl; break; default: cout << "Observer2 recv unknow msg!" << endl; break; } } };
class Observer3 : public Observer { public: void handle(int msgid) { switch (msgid) { case 1: cout << "Observer3 recv 1 msg!" << endl; break; case 3: cout << "Observer3 recv 3 msg!" << endl; break; default: cout << "Observer3 recv unknow msg!" << endl; break; } } };
class Subject { public: void addObserver(Observer* obser, int msgid) { _subMap[msgid].push_back(obser);
} void dispatch(int msgid) { auto it = _subMap.find(msgid); if (it != _subMap.end()) { for (Observer *pObser : it->second) { pObser->handle(msgid); } } } private: unordered_map<int, list<Observer*>> _subMap; };
int main() { Subject subject; Observer *p1 = new Observer1(); Observer *p2 = new Observer2(); Observer *p3 = new Observer3();
subject.addObserver(p1, 1); subject.addObserver(p1, 2); subject.addObserver(p2, 2); subject.addObserver(p3, 1); subject.addObserver(p3, 3);
int msgid = 0; for (;;) { cout << "输入消息id:"; cin >> msgid; if (msgid == -1) break; subject.dispatch(msgid); } return 0; }
|