工廠模式主要是為創(chuàng)建對象提供過渡接口,以便將創(chuàng)建對象的具體過程屏蔽隔離起來,達(dá)到提高靈活性的目的。
創(chuàng)新互聯(lián)服務(wù)緊隨時代發(fā)展步伐,進(jìn)行技術(shù)革新和技術(shù)進(jìn)步,經(jīng)過10年的發(fā)展和積累,已經(jīng)匯集了一批資深網(wǎng)站策劃師、設(shè)計(jì)師、專業(yè)的網(wǎng)站實(shí)施團(tuán)隊(duì)以及高素質(zhì)售后服務(wù)人員,并且完全形成了一套成熟的業(yè)務(wù)流程,能夠完全依照客戶要求對網(wǎng)站進(jìn)行做網(wǎng)站、網(wǎng)站設(shè)計(jì)、建設(shè)、維護(hù)、更新和改版,實(shí)現(xiàn)客戶網(wǎng)站對外宣傳展示的首要目的,并為客戶企業(yè)品牌互聯(lián)網(wǎng)化提供全面的解決方案。
定義一個用于創(chuàng)建對象的接口,讓其子類來決定實(shí)例化哪一個類(產(chǎn)品),工廠方法使一個類的創(chuàng)建延遲到其子類中。
工廠模式分為三種:
1)簡單工廠模式(Simple Factory)
2)工廠方法模式(Factory Method)
3)抽象工廠模式(Abstract Factory)
一、簡單工廠模式:
簡單工廠模式(Simple Factory)看為工廠方法模式(Factory Method)的一種特例,從接來下的實(shí)例可以看出。
1、組成:
1) 工廠類角色:這是本模式的核心,含有一定的商業(yè)邏輯和判斷邏輯。在java中它往往由一個具體類實(shí)現(xiàn)。
2) 抽象產(chǎn)品角色:它一般是具體產(chǎn)品繼承的父類或者實(shí)現(xiàn)的接口。在java中由接口或者抽象類來實(shí)現(xiàn)。
3) 具體產(chǎn)品角色:工廠類所創(chuàng)建的對象就是此角色的實(shí)例。在java中由一個具體類實(shí)現(xiàn)。
2、UML類圖:
3、相關(guān)代碼:
JAVA:
Factory .java:
// 工廠類角色
public class Factory {
public static AbstractProduct getAnProduct( String s){
if (s.equalsIgnoreCase("product1")){
return new Product1();
}else if(s.equalsIgnoreCase("product2")){
return new Product2();
}else{
System.out.println("This type product is not exist in the factory!!!");
return null;
}
}
}
AbstractProduct .java:
// 抽象產(chǎn)品角色
public interface AbstractProduct {
public void doSomething();
}
Product1 .java:
// 具體產(chǎn)品角色
public class Product1 implements AbstractProduct {
@Override
public void doSomething() {
// TODO Auto-generated method stub
System.out.println("doSomething for Product1!!!");
}
}
Product2 .java:
// 具體產(chǎn)品角色
public class Product2 implements AbstractProduct {
@Override
public void doSomething() {
// TODO Auto-generated method stub
System.out.println("doSomething for Product2!!!");
}
}
testMain .java:
// 測試類
public class testMain {
/**
* @param args
*/
public static void main(String[] args) {
AbstractProduct p1 = Factory.getAnProduct("product1");
p1.doSomething();
AbstractProduct p2 = Factory.getAnProduct("product2");
p2.doSomething();
AbstractProduct p3 = Factory.getAnProduct("product1");
p3.doSomething();
AbstractProduct p4 = Factory.getAnProduct("product2");
p4.doSomething();
}
}
運(yùn)行結(jié)果:
doSomething for Product1!!!
doSomething for Product2!!!
doSomething for Product1!!!
doSomething for Product2!!!
C++:
//============================================================================
// Name : SimpleFactory.cpp
// Author : Yan chao
// Version :
// Copyright : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================
#include
using namespace std;
// 抽象產(chǎn)品角色
class AbstractProduct{
public:
AbstractProduct(){}
virtual void doSomething() = 0;
virtual ~AbstractProduct(){}
};
// 具體產(chǎn)品角色
class Product1 : public AbstractProduct{
public:
void doSomething(){
cout << "doSomething for Product1!!!" << endl;
}
};
// 具體產(chǎn)品角色
class Product2 : public AbstractProduct{
public:
void doSomething(){
cout << "doSomething for Product2!!!" << endl;
}
};
// 工廠類角色
class SimpleFactory{
public:
static AbstractProduct* getProduct(string s){
if ( s.compare("product1") == 0 ){
cout << "s1:" << s << endl;
return new Product1();
}else if( s.compare("product2") == 0 ){
cout << "s2:" << s << endl;
return new Product2();
}else{
cout << "This type product is not exist in the factory!!!" << endl;
return NULL;
}
}
};
int main() {
SimpleFactory::getProduct("product1")->doSomething();
SimpleFactory::getProduct("product2")->doSomething();
SimpleFactory::getProduct("product2")->doSomething();
return 0;
}
運(yùn)行結(jié)果:
s1:product1
doSomething for Product1!!!
s2:product2
doSomething for Product2!!!
s2:product2
doSomething for Product2!!!
我們從開閉原則(對擴(kuò)展開放,對修改封閉)上來分析下簡單工廠模式。當(dāng)我們想增加了一個產(chǎn)品的時候,只要符合抽象產(chǎn)品的規(guī)則,那么只要通知工廠類知道就可以被客戶使用了。所以對產(chǎn)品部分來說,它是符合開閉原則的;但是工廠部分好像不太理想,因?yàn)槊吭黾右粋€產(chǎn)品,都要在工廠類中增加相應(yīng)的業(yè)務(wù)邏輯或者判斷邏輯,這顯然是違背開閉原則的??上攵獙τ谛庐a(chǎn)品的加入,工廠類是很被動的。對于這樣的工廠類,我們稱它為全能類或者上帝類。
在實(shí)際應(yīng)用中,很可能產(chǎn)品是一個多層次的樹狀結(jié)構(gòu)。由于簡單工廠模式中只有一個工廠類來對應(yīng)這些產(chǎn)品,所以這可能會把我們的上帝累壞了,也累壞了我們這些程序員。所以,就有了工廠方法模式!
二、工廠方法模式:
工廠方法模式中,工廠類角色也抽象化了!這樣就有多個工廠類來分別對應(yīng)不同的產(chǎn)品了。
1、組成:
1) 抽象工廠角色: 這是工廠方法模式的核心,它與應(yīng)用程序無關(guān)。是具體工廠角色必須實(shí)現(xiàn)的接口或者必須繼承的父類。在java 中它由抽象類或者接口來實(shí)現(xiàn)。
2) 具體工廠角色:它含有和具體業(yè)務(wù)邏輯有關(guān)的代碼。由應(yīng)用程序調(diào)用以創(chuàng)建對應(yīng)的具體產(chǎn)品的對象。
3) 抽象產(chǎn)品角色:它是具體產(chǎn)品繼承的父類或者是實(shí)現(xiàn)的接口。在 java 中一般有抽象類或者接口來實(shí)現(xiàn)。
4) 具體產(chǎn)品角色:具體工廠角色所創(chuàng)建的對象就是此角色的實(shí)例。在 java 中由具體的類
來實(shí)現(xiàn)。
2、UML類圖:
3、代碼實(shí)現(xiàn):
JAVA:
AbstractFactory .java:// 抽象工廠角色
public abstract class AbstractFactory {
abstract AbstractProduct getAnProduct();
}
AbstractProduct.java:
// 抽象產(chǎn)品角色
public interface AbstractProduct {
public void doSomething();
}
Factory1.java:
// 具體工廠角色
public class Factory1 extends AbstractFactory {
@Override
AbstractProduct getAnProduct() {
// TODO Auto-generated method stub
return new Product1();
}
}
Factory2.java:
// 具體工廠角色
public class Factory2 extends AbstractFactory {
@Override
AbstractProduct getAnProduct() {
// TODO Auto-generated method stub
return new Product2();
}
}
Product1.java:
// 具體產(chǎn)品角色
public class Product1 implements AbstractProduct {
public void doSomething() {
// TODO Auto-generated method stub
System.out.println("doSomething for Product1!!!");
}
}
Product2.java:
// 具體產(chǎn)品角色
public class Product2 implements AbstractProduct {
public void doSomething() {
// TODO Auto-generated method stub
System.out.println("doSomething for Product2!!!");
}
}
testMain.java:
// 測試類
public class testMain {
/**
* @param args
*/
public static void main(String[] args) {
Factory1 fc1 = new Factory1();
Factory2 fc2 = new Factory2();
fc1.getAnProduct().doSomething();
fc1.getAnProduct().doSomething();
fc1.getAnProduct().doSomething();
fc2.getAnProduct().doSomething();
fc2.getAnProduct().doSomething();
fc2.getAnProduct().doSomething();
fc2.getAnProduct().doSomething();
}
}
運(yùn)行結(jié)果:
doSomething for Product1!!!
doSomething for Product1!!!
doSomething for Product1!!!
doSomething for Product2!!!
doSomething for Product2!!!
doSomething for Product2!!!
doSomething for Product2!!!
C++:
//============================================================================
// Name : Factory.cpp
// Author : Yan chao
// Version :
// Copyright : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================
#include
using namespace std;
class AbstractProduct{
public:
AbstractProduct(){}
virtual void doSomething() = 0;
virtual ~AbstractProduct(){}
};
class Product1 : public AbstractProduct{
public:
void doSomething(){
cout << "doSomething for Product1!!!" << endl;
}
};
class Product2 : public AbstractProduct{
public:
void doSomething(){
cout << "doSomething for Product2!!!" << endl;
}
};
class AbstractFactory {
public:
virtual AbstractProduct* getProduct()=0;
virtual ~AbstractFactory(){}
};
class Factory1 : public AbstractFactory{
public:
Product1* getProduct(){
return new Product1();
}
};
class Factory2 : public AbstractFactory{
public:
Product2* getProduct(){
return new Product2();
}
};
int main() {
Factory1* f1 = new Factory1();
Factory2* f2 = new Factory2();
f1->getProduct()->doSomething();
f1->getProduct()->doSomething();
f1->getProduct()->doSomething();
f2->getProduct()->doSomething();
f2->getProduct()->doSomething();
f2->getProduct()->doSomething();
return 0;
}
運(yùn)行結(jié)果:
doSomething for Product1!!!
doSomething for Product1!!!
doSomething for Product1!!!
doSomething for Product2!!!
doSomething for Product2!!!
doSomething for Product2!!!
可以看出工廠方法的加入,使得對象的數(shù)量成倍增長。當(dāng)產(chǎn)品種類非常多時,會出現(xiàn)大量的與之對應(yīng)的工廠對象,這不是我們所希望的。因?yàn)槿绻荒鼙苊膺@種情況,可以考慮使用簡單工廠模式與工廠方法模式相結(jié)合的方式來減少工廠類:即對于產(chǎn)品樹上類似的種類(一般是樹的葉子中互為兄弟的)使用簡單工廠模式來實(shí)現(xiàn)。
簡單工廠模式與工廠方法模式真正的避免了代碼的改動了?沒有。在簡單工廠模式中,新產(chǎn)品的加入要修改工廠角色中的判斷語句;而在工廠方法模式中,要么將判斷邏輯留在抽象工廠角色中,要么在客戶程序中將具體工廠角色寫死(就象上面的例子一樣)。而且產(chǎn)品對象創(chuàng)建條件的改變必然會引起工廠角色的修改。
三、抽象工廠模式:
可以說,抽象工廠模式和工廠方法模式的區(qū)別就在于需要創(chuàng)建對象的復(fù)雜程度上。而且抽象工廠模式是三個里面最為抽象、最具一般性的。
可以理解為,工廠方法模式中的產(chǎn)品是一維的,而抽象工廠模式中的產(chǎn)品的維度是多維的。(從下聯(lián)的類圖就可以看出來?。?/p>
舉個具體的例子說明:
上面的類圖的產(chǎn)品類的分了兩個維度的實(shí)例。一個維度是,寶馬車和奔馳車;另一個維度是,商務(wù)型和運(yùn)動型。
1、 抽象工廠模式的用意為:給客戶端提供一個接口,可以創(chuàng)建多個產(chǎn)品族中的產(chǎn)品對象。
2、使用抽象工廠模式還要滿足一下條件:
1) 系統(tǒng)中有多個產(chǎn)品族,而系統(tǒng)一次只可能消費(fèi)其中一族產(chǎn)品。
2) 同屬于同一個產(chǎn)品族的產(chǎn)品以其使用。
3、 組成(和工廠方法類一樣):
1) 抽象工廠角色: 這是工廠方法模式的核心,它與應(yīng)用程序無關(guān)。是具體工廠角色必須實(shí)現(xiàn)的接口或者必須繼承的父類。在java 中它由抽象類或者接口來實(shí)現(xiàn)。
2) 具體工廠角色:它含有和具體業(yè)務(wù)邏輯有關(guān)的代碼。由應(yīng)用程序調(diào)用以創(chuàng)建對應(yīng)的具體產(chǎn)品的對象。在java 中它由具體的類來實(shí)現(xiàn)。
3) 抽象產(chǎn)品角色:它是具體產(chǎn)品繼承的父類或者是實(shí)現(xiàn)的接口。在 java 中一般有抽象類或者接口來實(shí)現(xiàn)。
4) 具體產(chǎn)品角色:具體工廠角色所創(chuàng)建的對象就是此角色的實(shí)例。在 java 中由具體的類來實(shí)現(xiàn)。
4、UML類圖:
5、代碼實(shí)現(xiàn):
JAVA:
AbstractFactory.java:
// 抽象工廠角色
public abstract class AbstractFactory {
abstract AbstractProductA getProductA();
abstract AbstractProductB getProductB();
}
AbstractProductA.java:
// 抽象產(chǎn)品角色(A維度)
public interface AbstractProductA {
public void doSomething();
}
AbstractProductB.java:
// 抽象產(chǎn)品角色(B維度)
public interface AbstractProductB {
public void doSomething();
}
Factory1.java:
// 具體工廠角色
public class Factory1 extends AbstractFactory {
@Override
AbstractProductA getProductA() {
// TODO Auto-generated method stub
return new Product1A();
}
AbstractProductB getProductB() {
// TODO Auto-generated method stub
return new Product1B();
}
}
Factory2.java:
// 具體工廠角色
public class Factory2 extends AbstractFactory {
@Override
AbstractProductA getProductA() {
// TODO Auto-generated method stub
return new Product2A();
}
AbstractProductB getProductB() {
// TODO Auto-generated method stub
return new Product2B();
}
}
Product1A.java:
// 具體產(chǎn)品角色(A維度)
public class Product1A implements AbstractProductA {
public void doSomething() {
// TODO Auto-generated method stub
System.out.println("doSomething for Product1A!!!");
}
}
Product2A.java:
// 具體產(chǎn)品角色(A維度)
public class Product2A implements AbstractProductA {
public void doSomething() {
// TODO Auto-generated method stub
System.out.println("doSomething for Product2A!!!");
}
}
Product1B.java:
// 具體產(chǎn)品角色(B維度)
public class Product1B implements AbstractProductB {
public void doSomething() {
// TODO Auto-generated method stub
System.out.println("doSomething for Product1B!!!");
}
}
Product2B.java:
// 具體產(chǎn)品角色(B維度)
public class Product2B implements AbstractProductB {
public void doSomething() {
// TODO Auto-generated method stub
System.out.println("doSomething for Product2B!!!");
}
}
testMain.java:
// 測試類
public class testMain {
/**
* @param args
*/
public static void main(String[] args) {
Factory1 fc1 = new Factory1();
Factory2 fc2 = new Factory2();
fc1.getProductA().doSomething();
fc1.getProductB().doSomething();
fc1.getProductA().doSomething();
fc1.getProductB().doSomething();
fc2.getProductA().doSomething();
fc2.getProductB().doSomething();
fc2.getProductA().doSomething();
fc2.getProductB().doSomething();
}
}
運(yùn)行結(jié)果:
doSomething for Product1A!!!
doSomething for Product1B!!!
doSomething for Product1A!!!
doSomething for Product1B!!!
doSomething for Product2A!!!
doSomething for Product2B!!!
doSomething for Product2A!!!
doSomething for Product2B!!!