文章目錄
- 1. 解決問題
- 2. 應用場景
- 3. 實作如下:
- C++實作
- C語言實作
- 4. 缺點
1. 解決問題
在工廠方法模式中,我們賣衣服。此時我們為每一種衣服建立不同的工廠,帽子有一個工廠專門建立,褲子有一個工廠專門建立,T恤有一個工廠專門建立。這樣的方式保證了代碼設計的開閉原則(對擴充開發,對修改關閉),解決了簡單工廠模式中暴露的問題。
但是又凸顯了新的問題,假如現在優衣庫這個大工廠 裡面需要生産不同的種類的衣服,我們需要建立一堆工廠。同時香蕉共和國 這個另一個大工廠也需要生産不同種類的衣服,我們又需要建立一堆工廠。在這種情況下,代碼會增加很多重複邏輯。
于是抽象工廠模式推出,将帽子封裝為一個工廠, 支援生産優衣庫的帽子和香蕉共和國的帽子。将褲子封裝為另一個工廠,用來生産優衣庫的褲子和香蕉共和國的褲子。
2. 應用場景
- 對象之間存在關聯,兩個對象使用同一個工廠生産,降低程式複雜度,減少不必要的重複邏輯。
- 系統中有多個産品族,但每次隻使用其中的某一族産品。如有人隻喜歡穿某一個品牌的衣服和鞋
- 系統中提供了産品的類庫,且所有産品的接口相同,用戶端不依賴産品執行個體的建立細節和内部結構
- 對象數量比較龐大,維護多個工廠則程式的複雜度過高,由工廠方法模式變更為抽象工廠模式
3. 實作如下:
C++實作
實作功能:仍然是生産衣服,我們使用抽象工廠模式 将優衣庫的帽子和香蕉共和國的帽子統一生産,将優衣庫的褲子和香蕉共和國的褲子統一生産。
#include <iostream>
using namespace std;
class Hat{
public:
virtual void createHat(void) = 0;
virtual ~Hat(){}
};
/*優衣庫的帽子*/
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(){}
};
/*優衣庫的褲子*/
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;
};
/*優衣庫的工廠,用來建立優衣庫的衣服*/
class FactoryKu: public Factory{
public:
Hat *createHat(){
return new kuHat();
}
Paths *createPaths(){
return new kuPaths();
}
};
/*香蕉共和國的工廠,用來建立香蕉共和國的衣服*/
class FactoryBanan: public Factory {
public:
Hat *createHat(){
return new bananHat();
}
Paths *createPaths() {
return new bananPaths();
}
};
int main() {
/*建立一個優衣庫的工廠,進行優衣庫的衣服的生産,包括褲子和帽子*/
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語言實作
實作功能:工廠商店分别 售賣白蘋果、紅蘋果、白葡萄、紅葡萄
/*C語言實作抽象工廠模式*/
#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. 缺點
- 當增加一個新的産品族時隻需增加一個新的具體工廠,不需要修改原代碼,滿足開閉原則。(按照如上C++代碼,我們買衣服,當我們增加一種衣服:裙子的時候,隻需要增加一個新的生産裙子的工廠就可以,不需要修改原的衣服種類的代碼)
- 當産品族中需要增加一個新種類的産品時,則所有的工廠類都需要進行修改,不滿足開閉原則。(當我們又增加了名創優品的種類時,我們之前所有的類包括:hat,Paths,還有對應的工廠類都需要修改 )