設計模式之四-Factory模式
簡單工廠模式
簡單工廠模式是工廠模式中最簡單的一種,他可以用比較簡單的方式隱藏創建對象的細節,一般只需要告訴工廠類所需要的類型,工廠類就會返回需要的產品類,但客戶端看到的只是產品的抽象對象,無需關心到底是返回了哪個子類。客戶端唯一需要知道的具體子類就是工廠子類。除了這點,基本是達到了依賴倒轉原則的要求。
假如,我們不用工廠類,只用AbstractProduct和它的子類,那客戶端每次使用不同的子類的時候都需要知道到底是用哪一個子類,當類比較少的時候還沒什麽問題,但是當類比較多的時候,管理起來就非常的麻煩了,就必須要做大量的替換,一個不小心就會發生錯誤。
而使用了工廠類之後,就不會有這樣的問題,不管裏面多少個類,我只需要知道類型號即可。不過,這裏還有一個疑問,那就是如果我每次用工廠類創建的類型都不相同,這樣修改起來的時候還是會出現問題,還是需要大量的替換。所以簡單工廠模式一般應該於程序中大部分地方都只使用其中一種產品,工廠類也不用頻繁創建產品類的情況。這樣修改的時候只需要修改有限的幾個地方即可。
客戶只需要知道SimpleFactory就可以了,使用的時候也是使用的AbstractFactory,這樣客戶端只在第一次創建工廠的時候是知道具體的細節的,其他時候它都只知道AbstractFactory,這樣就完美的達到了依賴倒轉的原則。
常用的場景
例如部署多種數據庫的情況,可能在不同的地方要使用不同的數據庫,此時只需要在配置文件中設定數據庫的類型,每次再根據類型生成實例,這樣,不管下面的數據庫類型怎麽變化,在客戶端看來都是只有一個AbstractProduct,使用的時候根本無需修改代碼。提供的類型也可以用比較便於識別的字符串,這樣不用記很長的類名,還可以保存為配置文件。
這樣,每次只需要修改配置文件和添加新的產品子類即可。
所以簡單工廠模式一般應用於多種同類型類的情況,將這些類隱藏起來,再提供統一的接口,便於維護和修改。
優點
1.隱藏了對象創建的細節,將產品的實例化推遲到子類中實現。
2.客戶端基本不用關心使用的是哪個產品,只需要知道用哪個工廠就行了,提供的類型也可以用比較便於識別的字符串。
3.方便添加新的產品子類,每次只需要修改工廠類傳遞的類型值就行了。
4.遵循了依賴倒轉原則。
缺點
1.要求產品子類的類型差不多,使用的方法名都相同,如果類比較多,而所有的類又必須要添加一種方法,則會是非常麻煩的事情。或者是一種類另一種類有幾種方法不相同,客戶端無法知道是哪一個產品子類,也就無法調用這幾個不相同的方法。
2.每添加一個產品子類,都必須在工廠類中添加一個判斷分支,這違背了開放-封閉原則。
C++實現代碼
#ifndef _ABSTRACTPRODUCT_H_ #define _ABSTRACTPRODUCT_H_ #include <stdio.h> class AbstractProduct{ public: AbstractProduct(); virtual ~AbstractProduct(); public: virtual void operation() = 0; }; class ProductA:public AbstractProduct{ public: ProductA(); virtual ~ProductA(); public: void operation(); }; class ProductB:public AbstractProduct{ public: ProductB(); ~ProductB(); public: void operation(); }; #endif AbstractProduct.h
#include "AbstractProduct.h" AbstractProduct::AbstractProduct(){ } AbstractProduct::~AbstractProduct(){ } ProductA::ProductA(){ } ProductA::~ProductA(){ } void ProductA::operation(){ fprintf(stderr,"productA operation!\n"); } ProductB::ProductB(){ } ProductB::~ProductB(){ } void ProductB::operation(){ fprintf(stderr,"productB operation!\n"); } AbstractProduct.cpp
#ifndef _SIMPLEFACTORY_H_ #define _SIMPLEFACTROY_H_ #include <stdio.h> #include "AbstractProduct.h" class AbstractFactory{ public: AbstractFactory(); virtual ~AbstractFactory(); public: virtual AbstractProduct* createProduct(int type) = 0; }; class SimpleFactory:public AbstractFactory{ public: SimpleFactory(); ~SimpleFactory(); public: AbstractProduct* createProduct(int type); }; #endif SimpleFactory.h
#include "SimpleFactory.h" AbstractFactory::AbstractFactory(){ } AbstractFactory::~AbstractFactory(){ } SimpleFactory::SimpleFactory(){ } SimpleFactory::~SimpleFactory(){ } AbstractProduct* SimpleFactory::createProduct(int type){ AbstractProduct* temp = NULL; switch(type) { case 1: temp = new ProductA(); break; case 2: temp = new ProductB(); break; default: break; } return temp; } SimpleFactory.cpp
#include "SimpleFactory.h" int main(){ AbstractFactory* factory = new SimpleFactory(); AbstractProduct* product = factory->createProduct(1); product->operation(); delete product; product = NULL; product = factory->createProduct(2); product->operation(); delete product; product = NULL; return 0; } client.cpp
工廠模式
工廠模式基本與簡單工廠模式差不多,上面也說了,每次添加一個產品子類都必須在工廠類中添加一個判斷分支,這樣違背了開放-封閉原則,因此,工廠模式就是為了解決這個問題而產生的。
既然每次都要判斷,那我就把這些判斷都生成一個工廠子類,這樣,每次添加產品子類的時候,只需再添加一個工廠子類就可以了。這樣就完美的遵循了開放-封閉原則。但這其實也有問題,如果產品數量足夠多,要維護的量就會增加,好在一般工廠子類只用來生成產品類,只要產品子類的名稱不發生變化,那麽基本工廠子類就不需要修改,每次只需要修改產品子類就可以了。
同樣工廠模式一般應該於程序中大部分地方都只使用其中一種產品,工廠類也不用頻繁創建產品類的情況。這樣修改的時候只需要修改有限的幾個地方即可。
常用的場景
基本與簡單工廠模式一致,只不過是改進了簡單工廠模式中的開放-封閉原則的缺陷,使得模式更具有彈性。將實例化的過程推遲到子類中,由子類來決定實例化哪個。
優點
基本與簡單工廠模式一致,多的一點優點就是遵循了開放-封閉原則,使得模式的靈活性更強。
缺點
與簡單工廠模式差不多。
C++實現代碼
#ifndef _ABSTRACTPRODUCT_H_ #define _ABSTRACTPRODUCT_H_ #include <stdio.h> class AbstractProduct{ public: AbstractProduct(); virtual ~AbstractProduct(); public: virtual void operation() = 0; }; class ProductA:public AbstractProduct{ public: ProductA(); virtual ~ProductA(); public: void operation(); }; class ProductB:public AbstractProduct{ public: ProductB(); ~ProductB(); public: void operation(); }; #endif AbstractProduct.h
#include "AbstractProduct.h" AbstractProduct::AbstractProduct(){ } AbstractProduct::~AbstractProduct(){ } ProductA::ProductA(){ } ProductA::~ProductA(){ } void ProductA::operation(){ fprintf(stderr,"productA operation!\n"); } ProductB::ProductB(){ } ProductB::~ProductB(){ } void ProductB::operation(){ fprintf(stderr,"productB operation!\n"); } AbstractProduct.cpp
#ifndef _SIMPLEFACTORY_H_ #define _SIMPLEFACTROY_H_ #include <stdio.h> #include "AbstractProduct.h" class AbstractFactory{ public: AbstractFactory(); virtual ~AbstractFactory(); public: virtual AbstractProduct* createProduct() = 0; }; class FactoryA:public AbstractFactory{ public: FactoryA(); ~FactoryA(); public: AbstractProduct* createProduct(); }; class FactoryB:public AbstractFactory{ public: FactoryB(); ~FactoryB(); public: AbstractProduct* createProduct(); }; #endif AbstractFactory.h
#include "AbstractFactory.h" AbstractFactory::AbstractFactory(){ } AbstractFactory::~AbstractFactory(){ } FactoryA::FactoryA(){ } FactoryA::~FactoryA(){ } AbstractProduct* FactoryA::createProduct(){ AbstractProduct* temp = NULL; temp = new ProductA(); return temp; } FactoryB::FactoryB(){ } FactoryB::~FactoryB(){ } AbstractProduct* FactoryB::createProduct(){ AbstractProduct* temp = NULL; temp = new ProductB(); return temp; } AbstractFactory.cpp
#include "AbstractFactory.h" int main(){ AbstractFactory* factory = new FactoryA(); AbstractProduct* product = factory->createProduct(); product->operation(); delete product; product = NULL; delete factory; factory = NULL; factory = new FactoryB(); product = factory->createProduct(); product->operation(); delete product; product = NULL; delete factory; factory = NULL; return 0; } client.cpp
抽象工廠模式
抽象工廠模式就變得比工廠模式更為復雜,就像上面提到的缺點一樣,工廠模式和簡單工廠模式要求產品子類必須要是同一類型的,擁有共同的方法,這就限制了產品子類的擴展。於是為了更加方便的擴展,抽象工廠模式就將同一類的產品子類歸為一類,讓他們繼承同一個抽象子類,我們可以把他們一起視作一組,然後好幾組產品構成一族。
此時,客戶端要使用時必須知道是哪一個工廠並且是哪一組的產品抽象類。每一個工廠子類負責產生一族產品,而子類的一種方法產生一種類型的產品。在客戶端看來只有AbstractProductA和AbstractProductB兩種產品,使用的時候也是直接使用這兩種產品。而通過工廠來識別是屬於哪一族產品。
產品ProductA_1和ProductB_1構成一族產品,對應於有Factory1來創建,也就是說Factory1總是創建的ProductA_1和ProductB_1的產品,在客戶端看來只需要知道是哪一類工廠和產品組就可以了。一般來說, ProductA_1和ProductB_1都是適應同一種環境的,所以他們會被歸為一族。
常用的場景
例如Linux和windows兩種操作系統下,有2個掛件A和B,他們在Linux和Windows下面的實現方式不同,Factory1負責產生能在Linux下運行的掛件A和B,Factory2負責產生能在Windows下運行的掛件A和B,這樣如果系統環境發生變化了,我們只需要修改工廠就行了。
優點
1.封裝了產品的創建,使得不需要知道具體是哪種產品,只需要知道是哪個工廠就行了。
2.可以支持不同類型的產品,使得模式靈活性更強。
3.可以非常方便的使用一族中間的不同類型的產品。
缺點
1.結構太過臃腫,如果產品類型比較多,或者產品族類比較多,就會非常難於管理。
2.每次如果添加一組產品,那麽所有的工廠類都必須添加一個方法,這樣違背了開放-封閉原則。所以一般適用於產品組合產品族變化不大的情況。
C++實現代碼
#ifndef _ABSTRACTPRODUCTA_H_ #define _ABSTRACTPRODUCTA_H_ #include <stdio.h> class AbstractProductA{ public: AbstractProductA(); virtual ~AbstractProductA(); public: virtual void operationA() = 0; }; class ProductA_1:public AbstractProductA{ public: ProductA_1(); virtual ~ProductA_1(); public: void operationA(); }; class ProductA_2:public AbstractProductA{ public: ProductA_2(); ~ProductA_2(); public: void operationA(); }; #endif AbstractProductA.h
#include "AbstractProductA.h" AbstractProductA::AbstractProductA(){ } AbstractProductA::~AbstractProductA(){ } ProductA_1::ProductA_1(){ } ProductA_1::~ProductA_1(){ } void ProductA_1::operationA(){ fprintf(stderr,"productA_1 operation!\n"); } ProductA_2::ProductA_2(){ } ProductA_2::~ProductA_2(){ } void ProductA_2::operationA(){ fprintf(stderr,"productA_2 operation!\n"); } AbstractProductA.cpp
#ifndef _ABSTRACTPRODUCTB_H_ #define _ABSTRACTPRODUCTB_H_ #include <stdio.h> class AbstractProductB{ public: AbstractProductB(); virtual ~AbstractProductB(); public: virtual void operationB() = 0; }; class ProductB_1:public AbstractProductB{ public: ProductB_1(); virtual ~ProductB_1(); public: void operationB(); }; class ProductB_2:public AbstractProductB{ public: ProductB_2(); ~ProductB_2(); public: void operationB(); }; #endif AbstractProductB.h
#include "AbstractProductB.h" AbstractProductB::AbstractProductB(){ } AbstractProductB::~AbstractProductB(){ } ProductB_1::ProductB_1(){ } ProductB_1::~ProductB_1(){ } void ProductB_1::operationB(){ fprintf(stderr,"productB_1 operation!\n"); } ProductB_2::ProductB_2(){ } ProductB_2::~ProductB_2(){ } void ProductB_2::operationB(){ fprintf(stderr,"productB_2 operation!\n"); } AbstractProductB.cpp
#ifndef _SIMPLEFACTORY_H_ #define _SIMPLEFACTROY_H_ #include <stdio.h> #include "AbstractProductA.h" #include "AbstractProductB.h" class AbstractFactory{ public: AbstractFactory(); virtual ~AbstractFactory(); public: virtual AbstractProductA* createProductA() = 0; virtual AbstractProductB* createProductB() = 0; }; class Factory1:public AbstractFactory{ public: Factory1(); ~Factory1(); public: AbstractProductA* createProductA(); AbstractProductB* createProductB(); }; class Factory2:public AbstractFactory{ public: Factory2(); ~Factory2(); public: AbstractProductA* createProductA(); AbstractProductB* createProductB(); }; #endif AbstractFactory.h
#include "AbstractFactory.h" AbstractFactory::AbstractFactory(){ } AbstractFactory::~AbstractFactory(){ } Factory1::Factory1(){ } Factory1::~Factory1(){ } AbstractProductA* Factory1::createProductA(){ AbstractProductA* temp = NULL; temp = new ProductA_1(); return temp; } AbstractProductB* Factory1::createProductB(){ AbstractProductB* temp = NULL; temp = new ProductB_1(); return temp; } Factory2::Factory2(){ } Factory2::~Factory2(){ } AbstractProductA* Factory2::createProductA(){ AbstractProductA* temp = NULL; temp = new ProductA_2(); return temp; } AbstractProductB* Factory2::createProductB(){ AbstractProductB* temp = NULL; temp = new ProductB_2(); return temp; } AbstractFactory.cpp
#include "AbstractFactory.h" int main(){ AbstractFactory* factory = new Factory1(); AbstractProductA* productA = factory->createProductA(); AbstractProductB* productB = factory->createProductB(); productA->operationA(); productB->operationB(); delete factory; factory = NULL; delete productA; productA = NULL; delete productB; productB = NULL; factory = new Factory2(); productA = factory->createProductA(); productB = factory->createProductB(); productA->operationA(); productB->operationB(); delete factory; factory = NULL; delete productA; productA = NULL; delete productB; productB = NULL; return 0; } client.cpp
轉載自http://www.cnblogs.com/cxjchen/p/3143633.html
設計模式之四-Factory模式