编程模式 之美 -- 抽象工厂模式
文章目錄
- 1. 解決問題
- 2. 應用場景
- 3. 實現(xiàn)如下:
- C++實現(xiàn)
- C語言實現(xiàn)
- 4. 缺點
1. 解決問題
在工廠方法模式中,我們賣衣服。此時我們?yōu)槊恳环N衣服創(chuàng)建不同的工廠,帽子有一個工廠專門創(chuàng)建,褲子有一個工廠專門創(chuàng)建,T恤有一個工廠專門創(chuàng)建。這樣的方式保證了代碼設(shè)計的開閉原則(對擴展開發(fā),對修改關(guān)閉),解決了簡單工廠模式中暴露的問題。
但是又凸顯了新的問題,假如現(xiàn)在優(yōu)衣庫這個大工廠 里面需要生產(chǎn)不同的種類的衣服,我們需要創(chuàng)建一堆工廠。同時香蕉共和國 這個另一個大工廠也需要生產(chǎn)不同種類的衣服,我們又需要創(chuàng)建一堆工廠。在這種情況下,代碼會增加很多重復邏輯。
于是抽象工廠模式推出,將帽子封裝為一個工廠, 支持生產(chǎn)優(yōu)衣庫的帽子和香蕉共和國的帽子。將褲子封裝為另一個工廠,用來生產(chǎn)優(yōu)衣庫的褲子和香蕉共和國的褲子。
2. 應用場景
- 對象之間存在關(guān)聯(lián),兩個對象使用同一個工廠生產(chǎn),降低程序復雜度,減少不必要的重復邏輯。
- 系統(tǒng)中有多個產(chǎn)品族,但每次只使用其中的某一族產(chǎn)品。如有人只喜歡穿某一個品牌的衣服和鞋
- 系統(tǒng)中提供了產(chǎn)品的類庫,且所有產(chǎn)品的接口相同,客戶端不依賴產(chǎn)品實例的創(chuàng)建細節(jié)和內(nèi)部結(jié)構(gòu)
- 對象數(shù)量比較龐大,維護多個工廠則程序的復雜度過高,由工廠方法模式變更為抽象工廠模式
3. 實現(xiàn)如下:
C++實現(xiàn)
實現(xiàn)功能:仍然是生產(chǎn)衣服,我們使用抽象工廠模式 將優(yōu)衣庫的帽子和香蕉共和國的帽子統(tǒng)一生產(chǎn),將優(yōu)衣庫的褲子和香蕉共和國的褲子統(tǒng)一生產(chǎn)。
#include <iostream>using namespace std;class Hat{public:virtual void createHat(void) = 0;virtual ~Hat(){}
};/*優(yōu)衣庫的帽子*/
class kuHat: public Hat {public:kuHat(){cout << "kuHat::kuHat()" << endl;}virtual void createHat(void) {cout << "kuHat::createHat()" << endl;}~kuHat(){cout << "kuHat::delete()" << endl;}
};/*香蕉共和國的帽子*/
class bananHat: public Hat{public:bananHat(){cout << "bananHat::bananHat()" << endl;}virtual void createHat(void) {cout << "bananHat::createHat()" << endl;}~bananHat(){cout << "bananHat::delete()" << endl;}
};class Paths{public:virtual void createPaths(void) = 0;virtual ~Paths(){}
};/*優(yōu)衣庫的褲子*/
class kuPaths: public Paths{public:kuPaths(){cout << "kuPaths::kuPaths()" << endl;}virtual void createPaths(void) {cout << "kuPaths::createPaths()" << endl;}~kuPaths(){cout << "kuPaths::delete()" << endl;}
};/*香蕉共和國的褲子*/
class bananPaths: public Paths{public:bananPaths(){cout << "bananPaths::bananPaths()" << endl;}virtual void createPaths(void) {cout << "bananPaths::createPaths()" << endl;}~bananPaths(){cout << "bananPaths::delete()" << endl;}
};/*抽象工廠類*/
class Factory {public:virtual Hat *createHat() = 0;virtual Paths *createPaths() = 0;
};/*優(yōu)衣庫的工廠,用來創(chuàng)建優(yōu)衣庫的衣服*/
class FactoryKu: public Factory{public:Hat *createHat(){return new kuHat();}Paths *createPaths(){return new kuPaths();}
};/*香蕉共和國的工廠,用來創(chuàng)建香蕉共和國的衣服*/
class FactoryBanan: public Factory {public:Hat *createHat(){return new bananHat();}Paths *createPaths() {return new bananPaths();}
};int main() {/*創(chuàng)建一個優(yōu)衣庫的工廠,進行優(yōu)衣庫的衣服的生產(chǎn),包括褲子和帽子*/Factory *factory1 = new FactoryKu();Hat *kuhat = factory1 -> createHat();Paths *kupaths = factory1 -> createPaths();kuhat -> createHat();kupaths -> createPaths();if(factory1) {delete factory1;factory1 = NULL;}if(kuhat) {delete kuhat;kuhat = NULL;}if(kupaths) {delete kupaths;kupaths = NULL;}return 0;
}
編譯運行如下
kuHat::kuHat()
kuPaths::kuPaths()
kuHat::createHat()
kuPaths::createPaths()
kuHat::delete()
kuPaths::delete()
C語言實現(xiàn)
實現(xiàn)功能:工廠商店分別 售賣白蘋果、紅蘋果、白葡萄、紅葡萄
/*C語言實現(xiàn)抽象工廠模式*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>enum {WHITE,RED};/*蘋果基類*/
typedef struct _Apple {void (*print_apple)(void);
}Apple;/*葡萄基類*/
typedef struct _Grape {void (*print_grape)(void);
}Grape;void print_white_apple(void)
{printf("I'am a white apple!\n");return;
}void print_red_apple(void)
{printf("I'am a red apple!\n");return;
}
void print_white_grape(void)
{printf("I'am a white grape!\n");return;
}
void print_red_grape(void)
{printf("I'am a red grape!\n");return;
}/*水果商店*/
typedef struct _FruitShop {Apple * (*sell_apple)(void);Grape * (*sell_grape)(void);
}FruitShop;Apple* sell_white_apple(void)
{Apple* tmp_apple = (Apple*)malloc(sizeof(Apple));assert(NULL != tmp_apple);tmp_apple->print_apple = print_white_apple;return tmp_apple;
}Apple* sell_red_apple(void)
{Apple* tmp_apple = (Apple*)malloc(sizeof(Apple));assert(NULL != tmp_apple);tmp_apple->print_apple = print_red_apple;return tmp_apple;
}Grape* sell_white_grape(void)
{Grape* tmp_grape = (Grape*)malloc(sizeof(Grape));assert(tmp_grape != NULL);tmp_grape->print_grape = print_white_grape;return tmp_grape;
}
Grape* sell_red_grape(void)
{Grape* tmp_grape = (Grape*)malloc(sizeof(Grape));assert(tmp_grape);tmp_grape->print_grape = print_red_grape;return tmp_grape;
}/*工廠商店,賣不同顏色的蘋果和葡萄*/
FruitShop* create_fruit_shop(int color)
{FruitShop* fruitshop = (FruitShop*)malloc(sizeof(FruitShop));assert(fruitshop != NULL);if (color == WHITE) {fruitshop->sell_apple = sell_white_apple;fruitshop->sell_grape = sell_white_grape;}else if (color == RED) {fruitshop->sell_apple = sell_red_apple;fruitshop->sell_grape = sell_red_grape;}return fruitshop;
}int main()
{FruitShop* fruitshop = create_fruit_shop(RED);Apple *ap = fruitshop->sell_apple();Grape *gp = fruitshop->sell_grape();ap->print_apple();gp->print_grape();if (ap != NULL) {free(ap);}if (gp != NULL) {free(gp);}if (fruitshop != NULL) {free(fruitshop);}return 0;
}
輸出如下:
I'am a red apple!
I'am a red grape!
4. 缺點
抽象工廠模式 的擴展有一定的“開閉原則”傾向性:
- 當增加一個新的產(chǎn)品族時只需增加一個新的具體工廠,不需要修改原代碼,滿足開閉原則。(按照如上C++代碼,我們買衣服,當我們增加一種衣服:裙子的時候,只需要增加一個新的生產(chǎn)裙子的工廠就可以,不需要修改原的衣服種類的代碼)
- 當產(chǎn)品族中需要增加一個新種類的產(chǎn)品時,則所有的工廠類都需要進行修改,不滿足開閉原則。(當我們又增加了名創(chuàng)優(yōu)品的種類時,我們之前所有的類包括:hat,Paths,還有對應的工廠類都需要修改 )
總結(jié)
以上是生活随笔為你收集整理的编程模式 之美 -- 抽象工厂模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: “月晦寒食天”下一句是什么
- 下一篇: 设计模式 之美 -- 建造者模式