1.设计模式概述
参考
目标:高内聚、低耦合、易实现、易测试、易维护、易扩展
1.1 创建型
创建型设计模式用来解决类的实例化或者对象的创建,所以又可以分为创建类和创建对象两种类型。
主要包含:工厂方法、抽象工厂、建造者、单例、对象池和原型。
应用场景:
(1)数据库连接
假设创建了一个数据库连接类用来连接数据库,并且需要在代码的不同地方访问数据库。常见做法是,在需要的地方创建连接类的实例。因为每个实例都会有一个单独的对数据库的连接,所以最后会有多个对数据的连接。加入我们使用单例类设计模式,把数据库连接类设计成一个单例类,因为只能创建一个该类的实例,所以只会有一个连接。
(2)创建相似类的多个实例
如果你想创建一些相似类的多个实例,并且要做到低耦合,那么你可以采用工厂设计模式。采用了工厂模式的类作为这些相似类之间的桥梁。比如开发时使用SQL Server数据库,但是将来想更换成oracle数据库,常规做法只能修改全部代码,但如果使用了工厂模式,情况就不同了。
1.2 结构性
怎样安排不同的类和对象,来形成更大的结构并且实现新的功能?这就是结构型设计模式所要解决的问题。
通过组织类与对象的结构来更方便地实现新功能,扩展功能。
主要包含:适配器、桥接、组件、装饰、外观、享元、私有类数据和代理。
应用场景:
假设有两个不兼容的接口,需要在这两个接口间建立联系时,可以使用适配器模式。适配器模式可以将某个类的接口转换成符合用户要求的接口或者类,使得不兼容的接口可以同时工作。
1.3 行为型
行为模式是关于识别对象之间的常见通信模式并实现这些模式。
一种行为型设计模式就代表着一种功能,使用哪种设计模式,则可以添加相对应的功能。
主要包含:指责链、命令、解释器、迭代器、中介者、备忘录、空对象、观察者、状态、策略、模板方法和访问者。
应用场景:
当某个操作的具体步骤需要在子类中实现,但是又不想修改该操作的算法框架时,可以使用模板模式。我们希望模块的功能可以扩展,这样,在适应应用新的变化时,可以用另一种方式表现模块的功能。不可以修改源代码,你可以添加新代码,但是不能更改算法的框架,这时候就需要用到模板模式。
2.创建型设计模式
2.1 工厂方法——创建不同的产品
当需要扩展新类时,只需要修改库中代码,而客户端代码无需修改。
before
// A design without factory pattern
#include <iostream>
using namespace std;
// Library classes
class Vehicle {
public:
virtual void printVehicle() = 0;
};
class TwoWheeler : public Vehicle {
public:
void printVehicle() {
cout << "I am two wheeler" << endl;
}
};
class FourWheeler : public Vehicle {
public:
void printVehicle() {
cout << "I am four wheeler" << endl;
}
};
// Client (or user) class
class Client {
public:
Client(int type) {
// Client explicitly creates classes according to type
if (type == 1)
pVehicle = new TwoWheeler();
else if (type == 2)
pVehicle = new FourWheeler();
else
pVehicle = NULL;
}
~Client() {
if (pVehicle)
{
delete[] pVehicle;
pVehicle = NULL;
}
}
Vehicle* getVehicle() {
return pVehicle;
}
private:
Vehicle *pVehicle;
};
// Driver program
int main() {
Client *pClient = new Client(1);
Vehicle * pVehicle = pClient->getVehicle();
pVehicle->printVehicle();
return 0;
}
上述代码未使用工厂方法。当客户需要新增一个三轮车辆时,不仅需要修改库中的代码,客户端代码也需要重新编译。
after
// C++ program to demonstrate factory method design pattern
#include <iostream>
using namespace std;
enum VehicleType {
VT_TwoWheeler, VT_ThreeWheeler, VT_FourWheeler
};
// Library classes
class Vehicle {
public:
virtual void printVehicle() = 0;
static Vehicle* Create(VehicleType type);
};
class TwoWheeler : public Vehicle {
public:
void printVehicle() {
cout << "I am two wheeler" << endl;
}
};
class ThreeWheeler : public Vehicle {
public:
void printVehicle() {
cout << "I am three wheeler" << endl;
}
};
class FourWheeler : public Vehicle {
public:
void printVehicle() {
cout << "I am four wheeler" << endl;
}
};
// Factory method to create objects of different types.
// Change is required only in this function to create a new object type
Vehicle* Vehicle::Create(VehicleType type) {
if (type == VT_TwoWheeler)
return new TwoWheeler();
else if (type == VT_ThreeWheeler)
return new ThreeWheeler();
else if (type == VT_FourWheeler)
return new FourWheeler();
else return NULL;
}
// Client class
class Client {
public:
// Client doesn't explicitly create objects
// but passes type to factory method "Create()"
Client()
{
VehicleType type = VT_ThreeWheeler;
pVehicle = Vehicle::Create(type);
}
~Client() {
if (pVehicle) {
delete[] pVehicle;
pVehicle = NULL;
}
}
Vehicle* getVehicle() {
return pVehicle;
}
private:
Vehicle *pVehicle;
};
// Driver program
int main() {
Client *pClient = new Client();
Vehicle * pVehicle = pClient->getVehicle();
pVehicle->printVehicle();
return 0;
}
以上代码使用了工厂方法模式,将对象的显示创建封装到基类的静态方法中,降低了耦合。
使用说明
- 不在Client类显式创建对象(即调用构造函数, new),将对象的创建放到基类的静态方法中。使用时,只需要指定相应的类型即可
VehicleType
。
2.2 抽象工厂——创建不同产品族
抽象工厂被认为是工厂方法模式之上的抽象层。抽象工厂主要围绕超级工厂展开,一般工厂产生产品,超级工厂可以产生工厂。
通过接口创建相关连的对象族,而无需知道具体类。
before
//A design without abstract factory pattern
#include <iostream>
#define LINUX
using namespace std;
/**
* Abstract base product.
*/
class Widget {
public: