java設計模式之一 工廠模式

xz43發表於2011-02-24
Java主要有以下三種Factory模式:

Simple Factory模式
專門定義一個類來負責建立其它類的例項,被建立的例項通常都具有共同的父類。

Factory Method模式
將物件的建立交由父類中定義的一個標準方法來完成,而不是其建構函式,究竟應該建立何種物件由具體的子類負責決定。

Abstract Factory模式
提供一個共同的介面來建立相互關聯的多個物件。

一、Simple Factory模式

1、  在這裡,我們先定義水果(Fruit)介面:
public interface Fruit {
  void plant();  //水果是被種植的
  void enableEat();  //水果能吃
}
2、  蘋果(Apple)是對水果(Fruit)介面的實現:
public class Apple implements Fruit{
  public void plant(){
    System.out.println("種蘋果!");
  }
  public void enableEat(){
    System.out.println("蘋果好吃!");
  }
}
3、  葡萄(Grape)是對水果(Fruit)介面的實現:
public class Grape implements Fruit{
  public void plant(){
    System.out.println("種葡萄!");
  }
  public void enableEat(){
    System.out.println("葡萄好吃!");
  }
}
4、  鴨梨(Pear)是對水果(Fruit)介面的實現:
public class Pear implements Fruit{
  public void plant(){
    System.out.println("種鴨梨!");
  }
  public void enableEat(){
    System.out.println("鴨梨好吃!");
  }
}
5、定義買水果(BuyFruit)這一過程類:
public class BuyFruit {
  /**
  * 簡單工廠方法
  */
  public static Fruit buyFruit(String which){
    if (which.equalsIgnoreCase("apple")) {  //如果是蘋果,則返回蘋果例項
      return new Apple();
    }
    else if (which.equalsIgnoreCase("pear")){  //如果是鴨梨,則返回鴨梨例項
      return new Strawberry();
    }
    else if (which.equalsIgnoreCase("grape")) { //如果是葡萄,則返回葡萄例項
      return new Grape();
    }
    else{
      return null;
    }
  }
}
6、  編寫測試類:
public class FruitTest {
  public static void  main(String args[]){
    BuyFruit buy = new BuyFruit();   //開始買水果這個過程
    buy.buyFruit("apple").enableEat(); //呼叫蘋果的enableEat()方法
  }
}
7、  說明:
A:我要購買蘋果,只需向工廠角色(BuyFruit)請求即可。而工廠角色在接到請求後,會自行判斷建立和提供哪一個產品。
B:但是對於工廠角色(BuyFruit)來說,增加新的產品(比如說增加草莓)就是一個痛苦的過程。工廠角色必須知道每一種產品,如何建立它們,以及何時向客戶端提供它們。換言之,接納新的產品意味著修改這個工廠。
C:因此Simple Factory模式的開放性比較差。
有什麼辦法可以解決這個問題嗎?那就需要Factory Method模式來為我們服務了。
 
二、Factory Method模式
 
1、同樣,我們先定義水果(Fruit)介面:
public interface Fruit {
  void plant();  //水果是被種植的
  void enableEat();  //水果能吃
}
2、蘋果(Apple)是對水果(Fruit)介面的實現:
public class Apple implements Fruit{
  public void plant(){
    System.out.println("種蘋果!");
  }
  public void enableEat(){
    System.out.println("蘋果好吃!");
  }
}
3、葡萄(Grape)是對水果(Fruit)介面的實現:
public class Grape implements Fruit{
  public void plant(){
    System.out.println("種葡萄!");
  }
  public void enableEat(){
    System.out.println("葡萄好吃!");
  }
}
4、鴨梨(Pear)是對水果(Fruit)介面的實現:
public class Pear implements Fruit{
  public void plant(){
    System.out.println("種鴨梨!");
  }
  public void enableEat(){
    System.out.println("鴨梨好吃!");
  }
}
5、在這裡我們將買水果(BuyFruit)定義為介面類:
public interface BuyFruit{
  /**
  * 工廠方法
  */
  public Fruit buyFruit();   //定義買水果這一過程
}
6、買蘋果是(BuyApple)對買水果(BuyFruit)這個介面的實現
public class BuyApple implements BuyFruit{
  public Fruit buyFruit(){
    return new Apple();  //返回蘋果例項
}
}
7、買鴨梨是(BuyPear)對買水果(BuyFruit)這個介面的實現
public class BuyPear implements BuyFruit{
  public Fruit BuyPear (){
    return new Pear();  //返回鴨梨例項
}
}
8、買葡萄是(BuyGrape)對買水果(BuyFruit)這個介面的實現
public class BuyGrape implements BuyFruit{
  public Fruit BuyGrape (){
    return new Grape ();  //返回葡萄例項
}
}
9、編寫測試類:
public class FruitTest {
  public static void  main(String args[]){
    BuyApple buy = new BuyApple(); //開始買水果這個過程
    buy.buyFruit().enableEat();      //呼叫蘋果的enableEat()方法
  }
}
10、說明:
A:工廠方法模式和簡單工廠模式在結構上的不同是很明顯的。工廠方法模式的核心是一個抽象工廠類,而簡單工廠模式把核心放在一個具體類上。工廠方法模式可以允許很多具體工廠類從抽象工廠類中將建立行為繼承下來,從而可以成為多個簡單工廠模式的綜合,進而推廣了簡單工廠模式。
B:工廠方法模式退化後可以變得很像簡單工廠模式。設想如果非常確定一個系統只需要一個具體工廠類,那麼就不妨把抽象工廠類合併到具體的工廠類中去。由於反正只有一個具體工廠類,所以不妨將工廠方法改成為靜態方法,這時候就得到了簡單工廠模式。
C:如果需要加入一個新的水果,那麼只需要加入一個新的水果類以及它所對應的工廠類。沒有必要修改客戶端,也沒有必要修改抽象工廠角色或者其他已有的具體工廠角色。對於增加新的水果類而言,這個系統完全支援"開-閉"原則。
D:對Factory Method模式而言,它只是針對一種類別(如本例中的水果類Fruit),但如果我們還想買肉,那就不行了,這是就必須要Abstract Factory模式幫忙了。

三、Abstract Factory模式

1、同樣,我們先定義水果(Fruit)介面:
public interface Fruit {
  void plant();  //水果是被種植的
  void enableEat();  //水果能吃
}
2、蘋果(Apple)是對水果(Fruit)介面的實現:
public class Apple implements Fruit{
  public void plant(){
    System.out.println("種蘋果!");
  }
  public void enableEat(){
    System.out.println("蘋果好吃!");
  }
}
3、葡萄(Grape)是對水果(Fruit)介面的實現:
public class Grape implements Fruit{
  public void plant(){
    System.out.println("種葡萄!");
  }
  public void enableEat(){
    System.out.println("葡萄好吃!");
  }
}
4、鴨梨(Pear)是對水果(Fruit)介面的實現:
public class Pear implements Fruit{
  public void plant(){
    System.out.println("種鴨梨!");
  }
  public void enableEat(){
    System.out.println("鴨梨好吃!");
  }
}
5、  定義肉(Meat)介面:
public interface Meat {
  void feed();  //肉是餵養的
  void enableEat();  //肉能吃
}
6、  豬肉(BigMeat)是對肉(Meat)介面的實現:
public class BigMeat implements Meat{
  public void feed(){
    System.out.println("養豬!");
  }
  public void enableEat(){
    System.out.println("豬肉好吃!");
  }
}
7、  牛肉(CowMeat)是對肉(Meat)介面的實現:
public class CowMeat implements Meat {
  public void feed(){
    System.out.println("養牛!");
  }
  public void enableEat(){
    System.out.println("牛肉好吃!");
  }
}
8、  我們可以定義買貨人(Buyer)介面:
public interface Buyer {
  /**
   * 買水果工廠方法
   */
  public Fruit buyFruit(Fruit whichFruit);
  /**
   * 買肉的工廠方法
   */
  public Meat buyMeat(Meat whichMeat);
}
9、  我(MyBuyer)是對買貨人(Buyer)介面的實現:
public class MyBuyer implements Buyer{
  /**
   * 買水果工廠方法
   */
  public Fruit buyFruit(Fruit whichFruit){
     return whichFruit;
  }
  /**
   * 買肉的工廠方法
   */
  public Meat buyMeat(Meat whichMeat){
     return whichMeat;
  }
}
10、編寫測試類:
public class MyBuyerAbstractTest {
  public static void  main(String args[]){
    Fruit apple = new Apple();   //蘋果例項
    Meat big = new BigMeat();  //豬肉例項
    MyBuyer my = new MyBuyer();  //我是買者的例項
    my.buyFruit(apple).enableEat();  //我買蘋果
    my.buyMeat(big).enableEat();    //我買豬肉
  }
}
11、說明:
A:抽象工廠模式可以向客戶端提供一個介面,使得客戶端在不必指定產品的具體型別的情況下,建立多個產品族中的產品物件。這就是抽象工廠模式的用意。
B:抽象工廠模式是所有形態的工廠模式中最為抽象和最具一般性的一種形態。
C:抽象工廠模式與工廠方法模式的最大區別就在於,工廠方法模式針對的是一個產品(Fruit)等級結構;而抽象工廠模式則需要面對多個產品等級結構(Fruit、Meat)。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/9399028/viewspace-687874/,如需轉載,請註明出處,否則將追究法律責任。

相關文章