设计模式
分类:
创建型设计模式:主要用于描述如何创建对象
结构型设计模式:主要用于描述如何实现类和对象的组合
行为型设计模式:主要用于描述类或对象怎样交互以及怎样分配职责
1.单例模式
-
设计需求:一个类只能创建一个对象
-
应用场景:全局唯一的资源,日志记录器、网页库、字典库
-
实现步骤:
- 构造函数设计为私有
- 设置静态的成员函数(getInstance)
- 静态数据成员_pInstance
- 将析构函数设置为私有(防止用户自己多次delete,造成double free)
- 为了释放堆空间,设计静态的析构函数(destroy)
#include <stdlib.h> #include <pthread.h> #include <iostream> using std::cout; using std::endl; //单例模式自动释放4:pthread_once + atexit class Singleton { public: static Singleton *getInstance() { pthread_once(&_once, init); return _pInstance; } static void init() { _pInstance = new Singleton(); atexit(destroy); } static void destroy() { if(_pInstance) { delete _pInstance; _pInstance = nullptr; } } private: Singleton() { cout << "Singleton() " << endl; } ~Singleton() { cout << "~Singleton() " << endl; } private: static Singleton *_pInstance; static pthread_once_t _once; }; Singleton *Singleton::_pInstance = nullptr; pthread_once_t Singleton::_once = PTHREAD_ONCE_INIT;
-
自动释放
-
友元类形式进行设计:
给实现单例模式的类添加一个友元类,该类析构函数实现调用单例模式的destory()函数或者直接delete。主函数中定义该友元类。
-
内部类+静态数据成员方式
给实现单例模式的类定义个私有的内部类,该类析构函数实现调用单例模式的destory()函数或者直接delete,同时增加个该类的静态数据成员,在类外进行定义初始化。一定要设置成静态的,因为如果不设置成静态的,内部类的析构函数由外部类的析构函数负责调用,而外部类的析构函数不会随着程序结束自动调用,所以该情况下内部类的析构函数不会执行。
-
atexit的方式
用atexit()函数在new时注册destory()函数,当进程退出时会进行自动调用。
-
pthread_once + atexit方式,函数原型:
int pthread_once(pthread_once_t *once_control,void (*init_routine)(void)); pthread_once_t once_control = PTHREAD_ONCE_INIT;
以上三种方式为防止多线程时多次new只能使用饿汉模式,使用pthread_once(),保证了当once_control相同时,init_routine只调用一次,此时用饱汉、饿汉模式均可以。once_control为静态数据成员和init函数为静态成员函数,因为getInstance()函数为静态的,只能访问静态的数据成员和成员函数。
-
2.工厂模式
-
设计需求:封装对象创建时的不确定性
-
使用场景
- 简单对象不需要使用工厂模式;
- 复杂对象才需要使用工厂模式;
- 对于不确定的对象,可以使用工厂模式。
-
以图像对象的创建为例,UML如下:
3.观察者模式
-
设计需求:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都得到通知并被自动更新。
-
以在医院病房里,门铃响后,护士和婴儿的反应作为例子,UML如下:
-
对于观察者模式中的推模式和拉模式
-
推模式
在observer的update()函数的参数中加上Status的引用,在调用notify()函数时通过参数的传递,将状态值传递给observer。
-
拉模式
Oberver类中添加Subject的指针,当创建观察者时,就将Ring注册给观察者,当状态发生变化调用update()函数时,在update()内调用Subject的getStatus()就可以获取到状态。
-