做網(wǎng)站開發(fā)工資怎樣google搜索關鍵詞
簡單工廠模式、工廠方法模式、抽象工廠模式
- 1. 為什么需要工廠模式?
- 2. 簡單工廠模式
- 2.1. 定義
- 2.2. 代碼實現(xiàn)
- 2.3. 優(yōu)點
- 2.4. 缺點
- 2.5. 適用場景
- 3. 工廠方法模式
- 3.1. 有了簡單工廠模式為什么還需要有工廠方法模式?
- 3.2. 定義
- 3.3. 代碼實現(xiàn)
- 3.4. 主要優(yōu)點
- 3.5. 主要缺點
- 3.6. 適用場景
- 4. 抽象工廠模式
- 4.1. 產(chǎn)品等級結構與產(chǎn)品族
- 4.2. 為什么需要抽象工廠模式?
- 4.3. 定義
- 4.4. 代碼實現(xiàn)
- 4.5. 主要優(yōu)點
- 4.6. 主要缺點
- 4.7. 使用場景
- 5. 總結
1. 為什么需要工廠模式?
工廠模式(Factory Pattern)是一種創(chuàng)建型設計模式,它提供了一種創(chuàng)建對象的方式,將對象的實例化過程與客戶端代碼解耦(即創(chuàng)建與使用解耦)。工廠模式的主要目的是提供一種靈活的對象創(chuàng)建機制,以便根據(jù)需求創(chuàng)建不同類型的對象。
以下是一些需要使用工廠模式的情況:
-
封裝對象的創(chuàng)建邏輯:當對象的創(chuàng)建過程比較復雜,涉及到多個步驟或依賴關系時,可以使用工廠模式將對象的創(chuàng)建邏輯封裝到工廠類中。這樣客戶端代碼只需要與工廠類進行交互,而無需了解具體的創(chuàng)建細節(jié)。
-
實現(xiàn)對象的解耦:工廠模式可以將對象的實例化過程與客戶端代碼解耦,使得客戶端代碼不需要直接依賴具體的類。客戶端只需要通過工廠類來獲取所需的對象,使得代碼更加靈活和可維護。
-
統(tǒng)一管理對象的創(chuàng)建:通過工廠模式,可以將對象的創(chuàng)建集中在工廠類中進行管理,避免了代碼中多處重復的對象創(chuàng)建代碼。這樣可以更好地控制對象的創(chuàng)建邏輯,提高代碼的復用性和可維護性。
-
實現(xiàn)產(chǎn)品族的創(chuàng)建:工廠模式可以用于創(chuàng)建產(chǎn)品族,即一組相關或相互依賴的產(chǎn)品對象。通過定義不同的工廠類來創(chuàng)建不同的產(chǎn)品族,可以使得創(chuàng)建過程更加靈活,同時也符合開閉原則,方便擴展新的產(chǎn)品族。
2. 簡單工廠模式
2.1. 定義
簡單工廠模式(Simple Factory Pattern):定義一個工廠類,它可以根據(jù)參數(shù)的不同返回不同類的實例,被創(chuàng)建的實例通常都具有共同的父類。因為在簡單工廠模式中用于創(chuàng)建實例的方法是靜態(tài)(static)方法,因此簡單工廠模式又被稱為靜態(tài)工廠方法(Static Factory Method)模式,它屬于類創(chuàng)建型模式。
2.2. 代碼實現(xiàn)
#include <iostream>
#include <string>// 抽象產(chǎn)品類
class Product {
public:virtual void Use() = 0;
};// 具體產(chǎn)品類 A
class ConcreteProductA : public Product {
public:void Use() override {std::cout << "Using ConcreteProductA" << std::endl;}
};// 具體產(chǎn)品類 B
class ConcreteProductB : public Product {
public:void Use() override {std::cout << "Using ConcreteProductB" << std::endl;}
};// 簡單工廠類
class SimpleFactory {
public:// 根據(jù)傳入的參數(shù)創(chuàng)建不同的產(chǎn)品對象static Product* CreateProduct(const std::string& productType) {if (productType == "A") {return new ConcreteProductA();} else if (productType == "B") {return new ConcreteProductB();}return nullptr;}
};int main() {// 使用簡單工廠創(chuàng)建產(chǎn)品對象Product* productA = SimpleFactory::CreateProduct("A");if (productA) {productA->Use();delete productA;}Product* productB = SimpleFactory::CreateProduct("B");if (productB) {productB->Use();delete productB;}return 0;
}
2.3. 優(yōu)點
- 工廠類包含必要的判斷邏輯,可以決定在什么時候創(chuàng)建哪一個產(chǎn)品類的實例??蛻舳丝梢悦獬苯觿?chuàng)建產(chǎn)品對象的職責,而僅僅“消費”產(chǎn)品。簡單工廠模式實現(xiàn)了對象創(chuàng)建和使用的分離。
- 客戶端無須知道所創(chuàng)建的具體產(chǎn)品類的類名,只需要知道具體產(chǎn)品類所對應的參數(shù)即可。對于一些復雜的類名,通過簡單工廠模式可以在一定程度減少使用者的記憶量。
- 通過引入配置文件,可以在不修改任何客戶端代碼的情況下更換和增加新的具體產(chǎn)品類,在一定程度上提高了系統(tǒng)的靈活性。
2.4. 缺點
- 由于工廠類集中了所有產(chǎn)品的創(chuàng)建邏輯,職責過重,一旦不能正常工作,整個系統(tǒng)都要受到影響。
- 使用簡單工廠模式勢必會增加系統(tǒng)中類的個數(shù)(引入了新的工廠類),增加了系統(tǒng)的復雜度和理解難度。
- 系統(tǒng)擴展困難。一旦添加新產(chǎn)品就不得不修改工廠邏輯,在產(chǎn)品類型較多時,有可能造成工廠邏輯過于復雜,不利于系統(tǒng)的擴展和維護。
- 簡單工廠模式由于使用了靜態(tài)工廠方法,造成工廠角色無法形成基于繼承的等級結構。
2.5. 適用場景
- 工廠類負責創(chuàng)建的對象比較少。由于創(chuàng)建的對象較少,不會造成工廠方法中的業(yè)務邏輯太過復雜。
- 客戶端只知道傳入工廠類的參數(shù),對于如何創(chuàng)建對象并不關心。
3. 工廠方法模式
3.1. 有了簡單工廠模式為什么還需要有工廠方法模式?
在簡單工廠模式中只提供一個工廠類,該工廠類處于對產(chǎn)品類進行實例化的中心位置,它需要知道每個產(chǎn)品對象的創(chuàng)建細節(jié),并決定何時實例化哪一個產(chǎn)品類。簡單工廠模式最大的缺點是當有新產(chǎn)品要加入系統(tǒng)中時,必須修改工廠類,需要在其中加入必要的業(yè)務邏輯,這違背了開閉原則。此外,在簡單工廠模式中,所有的產(chǎn)品都由同一個工廠創(chuàng)建,工廠類職責較重,業(yè)務邏輯較為復雜,具體產(chǎn)品與工廠類之間的耦合度高,嚴重影響了系統(tǒng)的靈活性和擴展性,而工廠方法模式則可以很好地解決這一問題。在工廠方法模式中,不再提供一個統(tǒng)一的工廠類來創(chuàng)建所有的產(chǎn)品對象,而是針對不同的產(chǎn)品提供不同的工廠,系統(tǒng)提供一個與產(chǎn)品等級結構對應的工廠等級結構。工廠方法模式定義如下:
3.2. 定義
工廠方法模式(Factory Method Pattern):定義一個用于創(chuàng)建對象的接口,讓子類決定將哪一個類實例化。工廠方法模式讓一個類的實例化延遲到其子類。工廠方法模式又簡稱為工廠模式(Factory Pattern),又可稱作虛擬構造器模式(Virtual Constructor Pattern)或多態(tài)工廠模式(Polymorphic Factory Pattern)。工廠方法模式是一種類創(chuàng)建型模式。
3.3. 代碼實現(xiàn)
#include <iostream>
#include <string>// 抽象產(chǎn)品類
class Product {
public:virtual void Use() = 0;
};// 具體產(chǎn)品類 A
class ConcreteProductA : public Product {
public:void Use() override {std::cout << "Using ConcreteProductA" << std::endl;}
};// 具體產(chǎn)品類 B
class ConcreteProductB : public Product {
public:void Use() override {std::cout << "Using ConcreteProductB" << std::endl;}
};// 抽象工廠類
class Factory {
public:virtual Product* CreateProduct() = 0;
};// 具體工廠類 A
class ConcreteFactoryA : public Factory {
public:Product* CreateProduct() override {return new ConcreteProductA();}
};// 具體工廠類 B
class ConcreteFactoryB : public Factory {
public:Product* CreateProduct() override {return new ConcreteProductB();}
};int main() {// 使用工廠方法創(chuàng)建產(chǎn)品對象Factory* factoryA = new ConcreteFactoryA();Product* productA = factoryA->CreateProduct();if (productA) {productA->Use();delete productA;}delete factoryA;Factory* factoryB = new ConcreteFactoryB();Product* productB = factoryB->CreateProduct();if (productB) {productB->Use();delete productB;}delete factoryB;return 0;
}
工廠方法模式是簡單工廠模式的延伸,它繼承了簡單工廠模式的優(yōu)點,同時還彌補了簡單工廠模式的不足。工廠方法模式是使用頻率最高的設計模式之一,是很多開源框架和API類庫的核心模式。
3.4. 主要優(yōu)點
(1)在工廠方法模式中,工廠方法用來創(chuàng)建客戶所需要的產(chǎn)品,同時還向客戶隱藏了哪種具體產(chǎn)品類將被實例化這一細節(jié)。用戶只需要關心所需產(chǎn)品對應的工廠,無須關心創(chuàng)建細節(jié),甚至無須知道具體產(chǎn)品類的類名。
(2)基于工廠角色和產(chǎn)品角色的多態(tài)性設計是工廠方法模式的關鍵。它能夠讓工廠可以自主確定創(chuàng)建何種產(chǎn)品對象,而如何創(chuàng)建這個對象的細節(jié)則完全封裝在具體工廠內(nèi)部。工廠方法模式之所以又被稱為多態(tài)工廠模式,正是因為所有的具體工廠類都具有同一抽象父類。
(3)使用工廠方法模式的另一個優(yōu)點是在系統(tǒng)中加入新產(chǎn)品時,無須修改抽象工廠和抽象產(chǎn)品提供的接口,無須修改客戶端,也無須修改其他的具體工廠和具體產(chǎn)品,而只要添加一個具體工廠和具體產(chǎn)品就可以了。這樣,系統(tǒng)的可擴展性也就變得非常好,完全符合開閉原則。
3.5. 主要缺點
(1)在添加新產(chǎn)品時,需要編寫新的具體產(chǎn)品類,而且還要提供與之對應的具體工廠類,系統(tǒng)中類的個數(shù)將成對增加,在一定程度上增加了系統(tǒng)的復雜度,有更多的類需要編譯和運行,會給系統(tǒng)帶來一些額外的開銷。
(2)由于考慮到系統(tǒng)的可擴展性,需要引入抽象層,在客戶端代碼中均使用抽象層進行定義,增加了系統(tǒng)的抽象性和理解難度,且在實現(xiàn)時可能需要用到反射等技術,增加了系統(tǒng)的實現(xiàn)難度
3.6. 適用場景
(1)客戶端不知道其所需要的對象的類。在工廠方法模式中,客戶端不需要知道具體產(chǎn)品類的類名,只需要知道所對應的工廠即可,具體的產(chǎn)品對象由具體工廠類創(chuàng)建,可將具體工廠類的類名存儲在配置文件或數(shù)據(jù)庫中。
(2)抽象工廠類通過其子類來指定創(chuàng)建哪個對象。在工廠方法模式中,抽象工廠類只需要提供一個創(chuàng)建產(chǎn)品的接口,而由其子類來確定具體要創(chuàng)建的對象,利用面向對象的多態(tài)性和里氏代換原則,在程序運行時,子類對象將覆蓋父類對象,從而使得系統(tǒng)更容易擴展。
4. 抽象工廠模式
工廠方法模式通過引入工廠等級結構,解決了簡單工廠模式中工廠類職責太重的問題。但由于工廠方法模式中的每個工廠只生產(chǎn)一類產(chǎn)品,可能會導致系統(tǒng)中存在大量的工廠類,勢必會增加系統(tǒng)的開銷。此時,可以考慮將一些相關的產(chǎn)品組成一個“產(chǎn)品族”,由同一個工廠來統(tǒng)一生產(chǎn)。
4.1. 產(chǎn)品等級結構與產(chǎn)品族
在工廠方法模式中,具體工廠負責生產(chǎn)具體的產(chǎn)品,每個具體工廠對應一種具體產(chǎn)品,工廠方法具有唯一性。一般情況下,一個具體工廠中只有一個或者一組重載的工廠方法。但是,有時希望一個工廠可以提供多個產(chǎn)品對象,而不是單一的產(chǎn)品對象。例如一個電器工廠,它可以生產(chǎn)電視機、電冰箱、空調等多種電器,而不是只生產(chǎn)某一種電器。為了更好地理解抽象工廠模式,這里先引入如下兩個概念:(1)產(chǎn)品等級結構。產(chǎn)品等級結構即產(chǎn)品的繼承結構,例如一個抽象類是電視機,其子類有海爾電視機、海信電視機、TCL電視機,則抽象電視機與具體品牌的電視機之間構成了一個產(chǎn)品等級結構,抽象電視機是父類,而具體品牌的電視機是其子類。(2)產(chǎn)品族。在抽象工廠模式中,產(chǎn)品族是指由同一個工廠生產(chǎn)的,位于不同產(chǎn)品等級結構中的一組產(chǎn)品。例如海爾電器工廠生產(chǎn)的海爾電視機、海爾電冰箱,海爾電視機位于電視機產(chǎn)品等級結構中,海爾電冰箱位于電冰箱產(chǎn)品等級結構中,海爾電視機、海爾電冰箱構成了一個產(chǎn)品族。
只要指明一個產(chǎn)品所處的產(chǎn)品族以及它所屬的等級結構,就可以唯一確定這個產(chǎn)品。
4.2. 為什么需要抽象工廠模式?
當系統(tǒng)所提供的工廠生產(chǎn)的具體產(chǎn)品并不是一個簡單的對象,而是多個位于不同產(chǎn)品等級結構、屬于不同類型的具體產(chǎn)品時,就可以使用抽象工廠模式。抽象工廠模式是所有形式的工廠模式中最為抽象和最具一般性的一種形式。抽象工廠模式與工廠方法模式最大的區(qū)別在于,工廠方法模式針對的是一個產(chǎn)品等級結構,而抽象工廠模式需要面對多個產(chǎn)品等級結構,一個工廠等級結構可以負責多個不同產(chǎn)品等級結構中的產(chǎn)品對象的創(chuàng)建。當一個工廠等級結構可以創(chuàng)建出分屬于不同產(chǎn)品等級結構的一個產(chǎn)品族中的所有對象時,抽象工廠模式比工廠方法模式更為簡單、更有效率。
在上圖中,每一個具體工廠可以生產(chǎn)屬于一個產(chǎn)品族的所有產(chǎn)品,例如海爾工廠生產(chǎn)海爾電視機、海爾冰箱和海爾空調,所生產(chǎn)的產(chǎn)品又位于不同的產(chǎn)品等級結構中。如果使用工廠方法模式,實現(xiàn)上圖所示結構需要提供9個具體工廠,而使用抽象工廠模式只需要提供3個具體工廠,極大地減少了系統(tǒng)中類的個數(shù)。
4.3. 定義
抽象工廠模式為創(chuàng)建一組對象提供了一種解決方案。與工廠方法模式相比,抽象工廠模式中的具體工廠不只是創(chuàng)建一種產(chǎn)品,它負責創(chuàng)建一族產(chǎn)品。
抽象工廠模式(Abstract Factory Pattern):提供一個創(chuàng)建一系列相關或相互依賴對象的接口,而無須指定它們具體的類。抽象工廠模式又稱為Kit模式,它是一種對象創(chuàng)建型模式。
4.4. 代碼實現(xiàn)
#include <iostream>
#include <string>// 抽象產(chǎn)品類 A
class AbstractProductA {
public:virtual void Use() = 0;virtual ~AbstractProductA() {}
};// 具體產(chǎn)品類 A1
class ConcreteProductA1 : public AbstractProductA {
public:void Use() override {std::cout << "Using ConcreteProductA1" << std::endl;}
};// 具體產(chǎn)品類 A2
class ConcreteProductA2 : public AbstractProductA {
public:void Use() override {std::cout << "Using ConcreteProductA2" << std::endl;}
};// 抽象產(chǎn)品類 B
class AbstractProductB {
public:virtual void Use() = 0;virtual ~AbstractProductB() {}
};// 具體產(chǎn)品類 B1
class ConcreteProductB1 : public AbstractProductB {
public:void Use() override {std::cout << "Using ConcreteProductB1" << std::endl;}
};// 具體產(chǎn)品類 B2
class ConcreteProductB2 : public AbstractProductB {
public:void Use() override {std::cout << "Using ConcreteProductB2" << std::endl;}
};// 抽象工廠類
class AbstractFactory {
public:virtual AbstractProductA* CreateProductA() = 0;virtual AbstractProductB* CreateProductB() = 0;virtual ~AbstractFactory() {}
};// 具體工廠類 A
class ConcreteFactoryA : public AbstractFactory {
public:AbstractProductA* CreateProductA() override {return new ConcreteProductA1();}AbstractProductB* CreateProductB() override {return new ConcreteProductB1();}
};// 具體工廠類 B
class ConcreteFactoryB : public AbstractFactory {
public:AbstractProductA* CreateProductA() override {return new ConcreteProductA2();}AbstractProductB* CreateProductB() override {return new ConcreteProductB2();}
};int main() {// 使用抽象工廠創(chuàng)建產(chǎn)品對象AbstractFactory* factoryA = new ConcreteFactoryA();AbstractProductA* productA = factoryA->CreateProductA();AbstractProductB* productB = factoryA->CreateProductB();if (productA) {productA->Use();delete productA;}if (productB) {productB->Use();delete productB;}delete factoryA;AbstractFactory* factoryB = new ConcreteFactoryB();AbstractProductA* productA2 = factoryB->CreateProductA();AbstractProductB* productB2 = factoryB->CreateProductB();if (productA2) {productA2->Use();delete productA2;}if (productB2) {productB2->Use();delete productB2;}delete factoryB;return 0;
}
抽象工廠模式是工廠方法模式的進一步延伸,由于它提供了功能更為強大的工廠類并且具備較好的可擴展性,在軟件開發(fā)中得以廣泛應用,尤其是在一些框架和API類庫的設計中。
4.5. 主要優(yōu)點
(1)抽象工廠模式隔離了具體類的生成,使得客戶并不需要知道什么被創(chuàng)建。由于這種隔離,更換一個具體工廠就變得相對容易,所有的具體工廠都實現(xiàn)了在抽象工廠中聲明的那些公共接口,因此只需改變具體工廠的實例,就可以在某種程度上改變整個軟件系統(tǒng)的行為。
(2)當一個產(chǎn)品族中的多個對象被設計成一起工作時,它能夠保證客戶端始終只使用同一個產(chǎn)品族中的對象。
(3)增加新的產(chǎn)品族很方便,無須修改已有系統(tǒng),符合開閉原則。
4.6. 主要缺點
增加新的產(chǎn)品等級結構麻煩,需要對原有系統(tǒng)進行較大的修改,甚至需要修改抽象層代碼,這顯然會帶來較大的不便,違背了開閉原則。
4.7. 使用場景
(1)一個系統(tǒng)不應當依賴于產(chǎn)品類實例如何被創(chuàng)建、組合和表達的細節(jié),這對于所有類型的工廠模式都是很重要的,用戶無須關心對象的創(chuàng)建過程,將對象的創(chuàng)建和使用解耦。
(2)系統(tǒng)中有多于一個的產(chǎn)品族,而每次只使用其中某一個產(chǎn)品族??梢酝ㄟ^配置文件等方式來使得用戶可以動態(tài)改變產(chǎn)品族,也可以很方便地增加新的產(chǎn)品族。
(3)屬于同一個產(chǎn)品族的產(chǎn)品將在一起使用,這一約束必須在系統(tǒng)的設計中體現(xiàn)出來。同一個產(chǎn)品族中的產(chǎn)品可以是沒有任何關系的對象,但是它們都具有一些共同的約束。例如同一操作系統(tǒng)下的按鈕和文本框,按鈕與文本框之間沒有直接關系,但它們都是屬于某一操作系統(tǒng)的,此時具有一個共同的約束條件:操作系統(tǒng)的類型。
(4)產(chǎn)品等級結構穩(wěn)定,設計完成之后,不會向系統(tǒng)中增加新的產(chǎn)品等級結構或者刪除已有的產(chǎn)品等級結構。
5. 總結
簡單工廠模式適用于創(chuàng)建對象較少且變化不頻繁的情況,工廠方法模式適用于創(chuàng)建對象較多且需要靈活擴展的情況,而抽象工廠模式適用于創(chuàng)建一組相關對象的情況。
所有的工廠模式都強調一點:兩個類A和B之間的關系應該僅僅是A創(chuàng)建B或是A使用B,而不能兩種關系都有。將對象的創(chuàng)建和使用分離,也使得系統(tǒng)更加符合單一職責原則,有利于對功能的復用和系統(tǒng)的維護。此外,將對象的創(chuàng)建和使用分離還有一個好處:防止用來實例化一個類的數(shù)據(jù)和代碼在多個類中到處都是,可以將有關創(chuàng)建的知識搬移到一個工廠類中。因為有時候創(chuàng)建一個對象不只是簡單調用其構造函數(shù),還需要設置一些參數(shù),可能還需要配置環(huán)境。如果將這些代碼散落在每一個創(chuàng)建對象的客戶類中,勢必會出現(xiàn)代碼重復、創(chuàng)建蔓延的問題,而這些客戶類其實無須承擔對象的創(chuàng)建工作,只需使用已創(chuàng)建好的對象就可以了。此時,可以引入工廠類來封裝對象的創(chuàng)建邏輯和客戶代碼的實例化/配置選項。