上一篇:http://www.BkJia.com/kf/201205/132171.html
工廠模式屬於創建型模式,大致可以分為三類,簡單工廠模式、工廠方法模式、抽象工廠模式。
一. 簡單工廠模式
簡單工廠模式,它的主要特點是需要在工廠類中做判斷,從而創造相應的產品。當增加新的產品時,就需要修改工廠類。舉個例子,有一家電子產品生產廠家,它只有一個工廠,能夠生產兩種型號的產品,A 和 B。可以想像一下,A是電吹風,B是電風扇。客戶需要什麼樣的吹風類產品,一定要顯示地告訴生產工廠。
代碼實現:
[cpp] enum CTYPE {PRODUCT_A, PRODUCT_B};
//抽象產品類
class Product
{
public:
virtual void Show() = 0;
};
//具體產品A
class ProductA: public Product
{
public:
void Show() { cout<<"Product A"<<endl; }
};
//具體產品B
class ProductB: public Product
{
public:
void Show() { cout<<"Product B"<<endl; }
};
//唯一的工廠,可以生產兩種型號的產品,在內部判斷
class Factory
{
public:
Product* CreateProduct(enum CTYPE ctype)
{
if(ctype == PRODUCT_A) //工廠內部判斷
return new ProductA(); //生產產品A
else if(ctype == PRODUCT_A)
return new ProductB(); //生產產品B
else
return NULL;
}
};
int main()
{
Factory fac; //工廠
Product *pro = fac.CreateProduct(PRODUCT_A);//生產產品A
pro->Show();
return 0;
}
enum CTYPE {PRODUCT_A, PRODUCT_B};
//抽象產品類
class Product
{
public:
virtual void Show() = 0;
};
//具體產品A
class ProductA: public Product
{
public:
void Show() { cout<<"Product A"<<endl; }
};
//具體產品B
class ProductB: public Product
{
public:
void Show() { cout<<"Product B"<<endl; }
};
//唯一的工廠,可以生產兩種型號的產品,在內部判斷
class Factory
{
public:
Product* CreateProduct(enum CTYPE ctype)
{
if(ctype == PRODUCT_A) //工廠內部判斷
return new ProductA(); //生產產品A
else if(ctype == PRODUCT_A)
return new ProductB(); //生產產品B
else
return NULL;
}
};
int main()
{
Factory fac; //工廠
Product *pro = fac.CreateProduct(PRODUCT_A);//生產產品A
pro->Show();
return 0;
}缺點:
由於工廠類集中了所有實例的創建邏輯,違反了高內聚責任分配原則,將全部創建邏輯集中到了一個工廠類中;它所能創建的類只能是事先考慮到的,如果需要添加新的類,則就需要改變工廠類了。
打個比方:
這個工廠在剛建廠時,就要事先把以後的要生產的產品考慮好,部門劃分好。如果要生產新的產品,就要改變工廠的空間布局,部門也要重新劃分,這是很不利的。當然如果工廠以後發展不大,也就是創建的對象比較少時,還是可以用的。
二. 工廠方法模式
所謂工廠方法模式,是指定義一個用於創建對象的接口,讓子類決定實例化哪一個類。Factory Method使一個類的實例化延遲到其子類。
還以剛才的例子解釋,這家電子廠賺了不少錢,於是決定再開設一個廠,其中一個工廠專門用來生產A型號的產品,也就是只生產電吹風,而另一工廠專門用來生產B型號的產品,也就是只生產電風扇,這樣分工明確了。以後客戶要再下定單時,可以直接找到相關的工廠了,比如要A型號的產品,就找A工廠要,不再擔心下的定單是A,生產出來的是B產品了。
代碼實現:
[cpp] class Product
{
public:
virtual void Show() = 0;
};
//產品A
class ProductA: public Product
{
public:
void Show()
{
cout<<"Product A"<<endl;
}
};
//產品B
class ProductB: public Product
{
public:
void Show()
{
cout<<"Product B"<<endl;
}
};
//抽象工廠
class Factory
{
public:
virtual Product* CreateProduct() = 0;
};
//生產A的工廠
class FactoryA: public Factory
{
public:
Product* CreateProduct()
{
return new ProductA;
}
};
//生產B的工廠
class FactoryB: public Factory
{
public:
Product* CreateProduct()
{
return new ProductB;
}
};
int main()
{
Factory* fac = new FactoryA(); //A工廠
Product* p = fac->CreateProduct(); //生產產品
p->Show();
return 0;
}
class Product
{
public:
virtual void Show() = 0;
};
//產品A
class ProductA: public Product
{
public:
void Show()
{
cout<<"Product A"<<endl;
}
};
//產品B
class ProductB: public Product
{
public:
void Show()
{
cout<<"Product B"<<endl;
}
};
//抽象工廠
class Factory
{
public:
virtual Product* CreateProduct() = 0;
};
//生產A的工廠
class FactoryA: public Factory
{
public:
Product* CreateProduct()
{
return new ProductA;
}
};
//生產B的工廠
class FactoryB: public Factory
{
public:
Product* CreateProduct()
{
return new ProductB;
}
};
int main()
{
Factory* fac = new FactoryA(); //A工廠
Product* p = fac->CreateProduct(); //生產產品
p->Show();
return 0;
}
其實你會發現,工廠方法把簡單工廠的內部邏輯判斷移到了客戶端代碼來進行,你想要加功能,本來是改工廠類的,而現在是修改客戶端。
這有什麼好處呢?舉個例子,有三個客戶原來要A產品,現在改賣B產品,在代碼中體現為:
簡單工廠的處理:
[cpp] Factory fac; //工廠
Product *pro1 = fac.CreateProduct(PRODUCT_A);//生產產品A
Product *pro2 = fac.CreateProduct(PRODUCT_A);//生產產品A
Product *pro3 = fac.CreateProduct(PRODUCT_A);//生產產品A
//改為B產品,這裡要改三個地方
//Product *pro1 = fac.CreateProduct(PRODUCT_B);//生產產品B
//Product *pro2 = fac.CreateProduct(PRODUCT_B);//生產產品B
//Product *pro3 = fac.CreateProduct(PRODUCT_B);//生產產品B
pro1->Show();
pro2->Show();
pro3->Show();
Factory fac; //工廠
Product *pro1 = fac.CreateProduct(PRODUCT_A);//生產產品A
Product *pro2 = fac.CreateProduct(PRODUCT_A);//生產產品A
Product *pro3 = fac.CreateProduct(PRODUCT_A);//生產產品A
//改為B產品,這裡要改三個地方
//Product *pro1 = fac.CreateProduct(PRODUCT_B);//生產產品B
//Product *pro2 = fac.CreateProduct(PRODUCT_B);//生產產品B
//Product *pro3 = fac.CreateProduct(PRODUCT_B);//生產產品B
pro1->Show();
pro2->Show();
pro3->Show();工廠方法的處理:
[cpp] Factory* fac = new FactoryA(); //A工廠
//改為B產品,這裡只改一個地方
//Factory* fac = new FactoryB(); //B工廠
Product* pro1 = factory_A->CreateProduct(); //生產產品
Product* pro2 = factory_A->CreateProduct(); //生產產品
Product* pro3 = factory_A->CreateProduct(); //生產產品
pro1->Show();
pro2->Show();
pro3->Show();
Factory* fac = new FactoryA(); //A工廠
//改為B產品,這裡只改一個地方 www.2cto.com
//Factory* fac = new FactoryB(); //B工廠
Product* pro1 = factory_A->CreateProduct(); //生產產品
Product* pro2 = factory_A->CreateProduct(); //生產產品
Product* pro3 = factory_A->CreateProduct(); //生產產品
pro1->Show();
pro2->Show();
pro3->Show();這裡可以看到工廠方法的好處了吧,工廠方法模式是簡單工廠模式的進一步抽象和推廣,它集中封裝了對象的創建,使得要更換產品時,不需要做大的改動就可以實現,降低了客戶程序與產品對象的耦合。
優點:
相對於簡單工廠模式來說,這樣分工更加明確,當需要新產品時,就建一個新的工廠,而不是對原工廠類進行修改。這樣做滿足了"開放-封閉"原則,即可以擴展,不可修改。
缺點:
1. 每增加一種產品,就需要增加一個對象的工廠。在C++實現中,就是要定義一個個的工廠類。顯然,相比簡單工廠模式,工廠方法模式需要更多的類定義。
2. Factory 模式僅僅局限於一類類(就是說 Product 是一類,有一個共同的基類),如果我們要為不同類的類提供一個對象創建的接口,那就要用AbstractFactory了。
打個比方:
如果這家公司發展迅速,推出了很多新的產品,那麼就要開設相應的新工廠,一種產品一個工廠。這對於客戶來說是好事,分工明確了白;但對於工廠自己來說開銷也變大了。
如要我想要生產核心芯片,但是芯片不是產品,不能繼承於product類。因為產品和零部件,不是一類。
三. 抽象工廠模式
抽象工廠模式,它定義為提供一個創建一系列相關或相互依賴對象的接口,而無需指定它們具體的類。
還以上面的例子解釋,這家公司經營的還不錯,針對其核心技術都申請了專利,後來生始生產相關電子芯片了 (像三星一樣,即生產產品也生產芯片)。對於這種情況,我們不能在抽象產品類上繼承一個零部件,因為產品和芯片沒有什麼共同之處,完全是兩個領域。你要做芯片,就要專心做,當成一個新的領域,不能用以前產品的那一套流程。這樣劃分才明確,才能更好的實現高內聚,低耦合的明標。
[cpp] //抽象產品類
class Product
{
public:
virtual void Show() = 0;
};
//產品A
class ProductA: public Product
{
public:
void Show()
{
cout<<"Product A"<<endl;
}
};
//產品B
class ProductB: public Product
{
public:
void Show()
{
cout<<"Product B"<<endl;
}
};
//抽象芯片類
class Chip
{
public:
virtual void Show() = 0;
};
//芯片A
class ChipA: public Chip
{
public:
void Show()
{
cout<<"Chip A"<<endl;
}
};
//芯片B
class ChipB: public Chip
{
public:
void Show()
{
cout<<"Chip B"<<endl;
}
};
//抽象工廠類
class Factory
{
public:
virtual Product* CreateProduct() = 0;
virtual Chip* CreateChip() = 0;
};
//生產A的工廠
class FactoryA: public Factory
{
public:
Product* CreateProduct() //產品
{
return new ProductA;
}
Chip* CreateChip() //芯片
{
return new ChipA;
}
};
//生產B的工廠
class FactoryB: public Factory
{
public:
Product* CreateProduct() //產品
{
return new ProductB;
}
Chip* CreateChip() //芯片
{
return new ChipB;
}
};
int main()
{
Factory* factury = new FactoryA(); //A工廠
Product* product = factury->CreateProduct(); //生產產品
Chip* chip = factury->CreateChip(); //生產芯片
product->Show();
chip->Show();
return 0;
}
//抽象產品類
class Product
{
public:
virtual void Show() = 0;
};
//產品A
class ProductA: public Product
{
public:
void Show()
{
cout<<"Product A"<<endl;
}
};
//產品B
class ProductB: public Product
{
public:
void Show()
{
cout<<"Product B"<<endl;
}
};
//抽象芯片類
class Chip
{
public:
virtual void Show() = 0;
};
//芯片A
class ChipA: public Chip
{
public:
void Show()
{
cout<<"Chip A"<<endl;
}
};
//芯片B
class ChipB: public Chip
{
public:
void Show()
{
cout<<"Chip B"<<endl;
}
};
//抽象工廠類
class Factory
{
public:
virtual Product* CreateProduct() = 0;
virtual Chip* CreateChip() = 0;
};
//生產A的工廠
class FactoryA: public Factory
{
public:
Product* CreateProduct() //產品
{
return new ProductA;
}
Chip* CreateChip() //芯片
{
return new ChipA;
}
};
//生產B的工廠
class FactoryB: public Factory
{
public:
Product* CreateProduct() //產品
{
return new ProductB;
}
Chip* CreateChip() //芯片
{
return new ChipB;
}
};
int main()
{
Factory* factury = new FactoryA(); //A工廠
Product* product = factury->CreateProduct(); //生產產品
Chip* chip = factury->CreateChip(); //生產芯片
product->Show();
chip->Show();
return 0;
}
我們可以發現,抽象工廠比工廠模式所能處理的產品更多,最關健的是這些產品有不同的基類。
優點:
1. AbstractFactory 模式關鍵就是將這一組對象的創建封裝到一個用於創建對象的工廠類(ConcreteFactory)中,維護這樣一個工廠創建類總比維護 n 多相關對象的創建過程要簡單的多。
2. 它的最大好處是易於交換產品系列,比如我要B工廠的產品,只需要在客戶端代碼修改一處即可。
打個比方:
這時客戶只要知道A工廠是生產A類的產品和芯片的,B工廠是生產B類的,其它都不用關心,只要想要與A類相關的東東就去找A就行了。
四. 總結:
1. 簡單工廠模式,所有的產品都在工廠類中進行生產。功能單一時,沒有什麼問題,但是當增加很多新產品時,就要不斷的修改產品類,易於出錯,也違反了對修改是封閉的原則。
2. 工廠方法模式,每個工廠生產一種產品,這樣分工更加明確。當增加新產品時,只需增加一個工廠類,而不用修改原有工廠類,這樣工廠類的耦合度就降低了。
3. 抽象工廠模式,比工廠方法模式處理的情況更多。主要是對不同產品的處理,這時的工廠能夠生產多種產品,這多種產品雖然沒有共同基類,但是卻屬於一類,具體體現在都是由同一個工廠生產。
作者 lwbeyond