通過實現 Factory 方法(Java)的工廠示例

意圖:

定義用於建立物件的介面,但讓子類決定例項化哪個類。Factory Method 允許類將例項化推遲到子類。

UML 圖:

http://i.stack.imgur.com/HF19B.gif

Product: 它定義 Factory 方法建立的物件的介面。

ConcreteProduct: 實現產品介面

建立者: 宣告工廠方法

ConcreateCreator: 實現 Factory 方法以返回 ConcreteProduct 的例項

問題陳述:使用工廠方法建立遊戲工廠,工廠方法定義遊戲介面。

程式碼段:

import java.util.HashMap;

/* Product interface as per UML diagram */
interface Game{
    /* createGame is a complex method, which executes a sequence of game steps */
    public void createGame();
}

/* ConcreteProduct implementation as per UML diagram */
class Chess implements Game{
    public Chess(){
        createGame();
    }
    public void createGame(){
        System.out.println("---------------------------------------");
        System.out.println("Create Chess game");
        System.out.println("Opponents:2");
        System.out.println("Define 64 blocks");
        System.out.println("Place 16 pieces for White opponent");
        System.out.println("Place 16 pieces for Black opponent");
        System.out.println("Start Chess game");
        System.out.println("---------------------------------------");
    }
}
class Checkers implements Game{
    public Checkers(){
        createGame();
    }
    public void createGame(){
        System.out.println("---------------------------------------");
        System.out.println("Create Checkers game");
        System.out.println("Opponents:2 or 3 or 4 or 6");
        System.out.println("For each opponent, place 10 coins");
        System.out.println("Start Checkers game");
        System.out.println("---------------------------------------");
    }
}
class Ludo implements Game{
    public Ludo(){
        createGame();
    }
    public void createGame(){
        System.out.println("---------------------------------------");
        System.out.println("Create Ludo game");
        System.out.println("Opponents:2 or 3 or 4");
        System.out.println("For each opponent, place 4 coins");
        System.out.println("Create two dices with numbers from 1-6");
        System.out.println("Start Ludo game");
        System.out.println("---------------------------------------");
    }
}

/* Creator interface as per UML diagram */
interface IGameFactory {
    public Game getGame(String gameName);
}

/* ConcreteCreator implementation as per UML diagram */
class GameFactory implements IGameFactory {
        
    HashMap<String,Game> games = new HashMap<String,Game>();
    /*  
        Since Game Creation is complex process, we don't want to create game using new operator every time.
        Instead we create Game only once and store it in Factory. When client request a specific game, 
        Game object is returned from Factory instead of creating new Game on the fly, which is time consuming
    */
    
    public GameFactory(){
        
        games.put(Chess.class.getName(),new Chess());
        games.put(Checkers.class.getName(),new Checkers());
        games.put(Ludo.class.getName(),new Ludo());        
    }
    public Game getGame(String gameName){
        return games.get(gameName);
    }
}

public class NonStaticFactoryDemo{
    public static void main(String args[]){
        if ( args.length < 1){
            System.out.println("Usage: java FactoryDemo gameName");
            return;
        }
     
        GameFactory factory = new GameFactory();
        Game game = factory.getGame(args[0]);
        System.out.println("Game="+game.getClass().getName());
    }
}

輸出:

java NonStaticFactoryDemo ChessCreate Chess game
Opponents:2
Define 64 blocks
Place 16 pieces for White opponent
Place 16 pieces for Black opponent
Start Chess game---------------------------------------
Create Checkers game
Opponents:2 or 3 or 4 or 6
For each opponent, place 10 coins
Start Checkers game---------------------------------------
Create Ludo game
Opponents:2 or 3 or 4
For each opponent, place 4 coins
Create two dices with numbers from 1-6
Start Ludo gameGame=Chess

這個例子通過實現 FactoryMethod 來顯示 Factory 類。

  1. Game 是所有型別遊戲的介面。它定義了複雜的方法:createGame()

  2. Chess, Ludo, Checkers 是遊戲的不同變體,為 createGame() 提供實現

  3. public Game getGame(String gameName)IGameFactory 類中是 FactoryMethod

  4. GameFactory 在建構函式中預先建立不同型別的遊戲。它實現了 IGameFactory 工廠方法。

  5. 遊戲名稱作為命令列引數傳遞給 NotStaticFactoryDemo

  6. GameFactory 中的 getGame 接受遊戲名稱並返回相應的 Game 物件。

何時使用:

  1. Factory :當你不希望將物件例項化邏輯公開給客戶端/呼叫者時
  2. 抽象工廠 :當你想要為相關或從屬物件的族提供介面而不指定其具體類時
  3. 工廠方法: 定義用於建立物件的介面,但讓子類決定例項化哪個類

與其他創作模式比較:

  1. 設計從使用工廠方法開始 (不那麼複雜,可定製,子類增加)並向 Abstract Factory,Prototype 或 Builder 發展 (更靈活,更復雜),因為設計師發現需要更多靈活性的地方

  2. 抽象工廠類通常使用工廠方法實現,但也可以使用 Prototype 實現 ****

進一步閱讀的參考資料:原始碼設計模式