一般認爲,存在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