0x00 引言
设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案,之所以记录这些模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。重要的参考文献为设计模式-可复用的面向对象软件元素[1],以及菜鸟教程[2]上收录的一些成熟的设计模式。本文将根据菜鸟教程上的设计模式分类方式书写,且只针对创建型模式,全部代码基于c++。
0x01 创建型模式
这种设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用new运算符直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活。
1 | 1 工厂模式(Factory Pattern) |
1、工厂模式
设计一个工厂类,专门用来创建对象,根据用户的需求创建不同种类的对象。
假设有一个工厂能生产出A、B两种产品,当客户需要产品的时候要告诉工厂是A产品还是B产品。具体实现代码如下:
1 |
|
从上述代码可以看出,一个工厂为Product,其生产的两种产品分别为其继承类Product_A与Product_B,工厂类Factory实现了用户选择生产哪种产品的接口。
2、抽象工厂模式
抽象工厂模式是抽象工厂模式的升级版,现考虑一种情况,假设目前A产品中有A1和A2两种型号,B产品中有B1和B2两种型号,那么工厂模式就失效了(实际上引入两个参数不是也能解决这个问题么,这边假设就如他说的失效了吧。。),那么我们就需要两个工厂类,分别来生产A、B产品。具体实现代码如下:
1 |
|
从上述代码可见,实际上就是将工厂类Factory作为并新生成两个继承类FactoryA、FactoryB,分别用它们来控制生产A、B产品,且每个产品拥有自己的子型号产品product_A1、product_A2、product_B1、product_B2。
3、单例模式
所谓单例模式[3]的设计目的就是保证:1)确保一个类只有一个实例被建立;2)提供一个访问它的全局访问点。
该模式有两种实现方法:懒汉式与饿汉式。
当访问量较小的时候,采用懒汉式(个人推测耗用cpu少),以时间换空间。当有多线程存在时(即实例访问量较大),或者线程较多的情况下,优先采用饿汉式,以空间换时间。
3.1、懒汉式
该方法的技巧在于初始化时定义一个静态变量,且生成对象的时候采用该类的生成接口,每次调用都需要提前判断是否已被实例化,代码如下:
1 | class CSingleton |
可见一旦调用GetInstance函数,即能实例化对象。这种方式在单线程的情况下是可靠的,但如果程序是多线程的话有可能会重复构造(比如两个线程同时进入if(p == NULL))。
3.1.1 加锁的懒汉式
那么如何解决上述遇到的重复构造问题呢,实际上加个锁即可,代码如下:
1 | class CSingleton |
该方案也存在劣势,即会导致程序运行速度减慢,所以说懒汉式比较适用于访问量较小的情况。
3.1.2、内部静态变量的懒汉式(推荐)
还有一种方法也能解决重复构造的问题,且没有像加锁那样的减速缺点,但是需要在C++11及之后的版本使用,否则可能会导致多次构造函数调用。这种方法即以静态变量的方式实例化对象,这样就不会重复实例化了,代码如下:
1 | class CSingleton |
3.2、饿汉式
饿汉式是指在类加载的时候即new出该类对象,代码如下:
1 | class CSingleton |
4、建造者模式
所谓建造者模式[4]就是将一个复杂对象的构建与他的表示分离,这里采用《大话设计模式》中举的例子-建造小人来描述这种模式,代码如下:
1 | class Builder |
从main文件可以看出,当用户想捏小人的时候,不需要自己去寻找胖人或者瘦人的继承类,只需要调用指挥官的类,而想捏的小人只需当参数传入即可。
5、原型模式
同一个类可以被多次实例化,但是这样构造出来的对象都是一模一样的,无论是出于对每个对象的把控或是内存分配都不利。使用原型模式[5],可以在实例化的时候微微修改参数,从而复制出一个与原型类似的对象,代码如下:
1 |
|
从上述代码可以看出,实质上就是在该CConcretePrototype内部写了两个构造函数,一个是原型的构造函数,另一个是复制体的构造函数,当用户需要复制原型时,只需调用clone函数。
0x02 引用文献
[1]https://baike.baidu.com/item/设计模式:可复用面向对象软件的基础/7600072
[2]https://www.runoob.com/design-pattern/design-pattern-intro.html
[3]https://www.jianshu.com/p/69eef7651667
[4]https://blog.csdn.net/wuzhekai1985/article/details/6667467
[5]https://blog.csdn.net/cabinriver/article/details/8895372/