一般认为,存在23种面向对象设计模式,根据每种模式关注的侧重点不同,大致可以分为三大类:创建型模式(5种)、结构型模式(7种)和行为型模式(11种),具体划分如下:
创建型模式:简单工厂模式、工厂方法模式、抽象工厂模式、建造者模式、单例模式;
结构型模式:适配器模式、桥接模式、组合模式、装饰模式、外观模式、享元模式、代理模式;
行为型模式:职责链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式、访问者模式。
篇幅关系,将这三大类设计模式分三篇分别做个整理,今天就来对创建型模式做一个概览型描述。
创建型模式致力于通过抽象方法将对象的创建和使用分离。调用者只需知道对象的共同接口,而无需了解具体的实现细节,使得软件结构更加清晰,也更符合单一职责原则。
1. 简单工厂模式(Simple Factory Pattern)
简单工厂模式又称为静态工厂方法模式(Static Factory Method Pattern),在该模式下,可以通过使用不同的参数来获得不同类型的实例。简单工厂模式包含三个角色:
(1) 工厂角色Factory
(2) 抽象产品角色Product
(3) 具体产品角色ConcreteProduct
其中,工厂角色负责实现创建所有实例的内部逻辑;抽象产品角色是所创建的所有对象的父类,描述所有实例的公共接口;具体产品角色是最终创建的目标产品。
实例代码:
/*-------------------------------------------------------*/
// Factory.cpp
// Implementation of the Class Factory
/*-------------------------------------------------------*/
#include "Factory.h"
#include "ConcreteProductA.h"
#include "ConcreteProductB.h"
Product* Factory::createProduct(string proname)
{
if ( "A" == proname )
{
return new ConcreteProductA();
}
else if("B" == proname)
{
return new ConcreteProductB();
}
return NULL;
}
简单工厂模式适合于需要创建的对象比较少,且调用者不关心如何创建对象以及创建细节的情况,需要什么,只需要传入一个正确的参数,就可以获得所需要的对象。
2. 工厂方法模式(Factory Method Pattern)
工厂方法模式又称为工厂模式,或者虚拟构造器模式(Virtual Constructor Pattern)、多态工厂模式(Polymorphic Factory Pattern)。在该模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,通过工厂子类来确定究竟应该实例化哪一个具体的产品类。
工厂方法包含四个角色:
(1) 抽象工厂Factory
(2) 具体工厂ConcreteFactory
(3) 抽象产品Product
(4) 具体产品ConcreteProduct
示例代码:
#include "Factory.h"
#include "ConcreteFactory.h"
#include "Product.h"
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
Factory * fc = new ConcreteFactory();
Product * prod = fc->factoryMethod();
prod->use();
delete fc;
delete prod;
return 0;
}
/*------------------------------------------------*/
// ConcreteFactory.cpp
// Implementation of the Class ConcreteFactory
/*--------------------------------------------------*/
#include "ConcreteFactory.h"
#include "ConcreteProduct.h"
Product* ConcreteFactory::factoryMethod()
{
return new ConcreteProduct();
}
基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。在工厂方法模式中,抽象父类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏替换原则,用子类对象覆盖父类对象,使得系统容易扩展。
3. 抽象工厂模式(Abstract Factory Pattern)
抽象工厂模式又称为Kit模式,提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类。
抽象工厂模式包括四个角色:
(1) 抽象工厂AbstractFactory
(2) 具体工厂ConcreteFactory
(3) 抽象产品AbstractProduct
(4) 具体产品Product
示例代码:
#include <iostream>
#include "AbstractFactory.h"
#include "AbstractProductA.h"
#include "AbstractProductB.h"
#include "ConcreteFactory1.h"
#include "ConcreteFactory2.h"
using namespace std;
int main(int argc, char *argv[])
{
AbstractFactory * fc = new ConcreteFactory1();
AbstractProductA * pa = fc->createProductA();
AbstractProductB * pb = fc->createProductB();
pa->use();
pb->eat();
AbstractFactory * fc2 = new ConcreteFactory2();
AbstractProductA * pa2 = fc2->createProductA();
AbstractProductB * pb2 = fc2->createProductB();
pa2->use();
pb2->eat();
}
抽象工厂模式适用于系统中有多于一个产品族,且每次只使用其中的一个产品族的情况,属于同一个产品族的产品将在一起使用。系统提供一个产品类的库,所有的产品以同样的接口出现,从而使调用者不依赖于具体实现。
抽象工厂模式隔离了具体类的生成,使得更换一个具体工厂变得相对容易。所有的具体工厂都实现了抽象工厂中定义的公共接口,因此只需改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。
4. 建造者模式(Builder Pattern)
建造者模式又称为生成器模式,是将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。建造者模式允许用户只通过指定复杂对象的类型和内容即可将其创建出来,用户不需要知道内部的具体构建细节。
标准的创建者模式一般包含4个角色:
(1) 抽象建造者Builder
(2) 具体建造者ConcreteBuilder
(3) 指挥者Director
(4) 最终产品Product
其中,Director类用于隔离客户与生产过程,并负责控制产品的生产过程。指挥者针对抽象建造者编程,调用者只需要知道具体建造者的类型,即可通过指挥者类调用建造者的相关方法,返回一个完整的产品对象。
示例代码:
#include <iostream>
#include "ConcreteBuilder.h"
#include "Director.h"
#include "Builder.h"
#include "Product.h"
using namespace std;
int main(int argc, char *argv[])
{
ConcreteBuilder * builder = new ConcreteBuilder();
Director director;
director.setBuilder(builder);
Product * pd = director.constuct();
pd->show();
delete builder;
delete pd;
return 0;
}
建造者模式适用的场景:需要生成的产品对象具有较复杂的内部结构,通常包含多个成员属性;且各个属性相互依赖,需要指定其生成顺序;需要将对象的创建过程从创建该对象的类中独立出来,或者需要隔离复杂对象的创建和适用,使相同的创建过程可以创建不同类型的产品。
5. 单例模式 (Single Pattern)
单例模式下,一个类只有一个实例,该类自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。
示例代码:
#include <iostream>
#include "Singleton.h"
using namespace std;
int main(int argc, char *argv[])
{
Singleton * sg = Singleton::getInstance();
sg->singletonOperation();
return 0;
}
/*-------------------------------------------------------*/
// Singleton.cpp
// Implementation of the Class Singleton
/*-------------------------------------------------------*/
#include "Singleton.h"
#include <iostream>
using namespace std;
Singleton * Singleton::instance = NULL;
Singleton::Singleton()
{
}
Singleton::~Singleton()
{
delete instance;
}
Singleton* Singleton::getInstance()
{
if (instance == NULL)
{
instance = new Singleton();
}
return instance;
}
void Singleton::singletonOperation()
{
cout << "singletonOperation" << endl;
}
单例类拥有一个私有的构造函数,以确保用户不能通过new关键字直接创建实例。单例模式有如下三个特点:
(1) 单例类的构造函数为私有;
(2) 提供一个自身的静态私有成员变量(确保自身只有一份拷贝);
(3) 提供一个公有的静态工厂方法(唯一的公共访问点)。
主要参考资料:https://design-patterns.readthedocs.io/zh_CN/latest/read_uml.html