通过实现 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
类。
-
Game
是所有类型游戏的界面。它定义了复杂的方法:createGame()
-
Chess, Ludo, Checkers
是游戏的不同变体,为createGame()
提供实现 -
public Game getGame(String gameName)
在IGameFactory
类中是FactoryMethod
-
GameFactory
在构造函数中预先创建不同类型的游戏。它实现了IGameFactory
工厂方法。 -
游戏名称作为命令行参数传递给
NotStaticFactoryDemo
-
GameFactory
中的getGame
接受游戏名称并返回相应的Game
对象。
何时使用:
- Factory :当你不希望将对象实例化逻辑公开给客户端/调用者时
- 抽象工厂 :当你想要为相关或从属对象的族提供接口而不指定其具体类时
- 工厂方法: 定义用于创建对象的接口,但让子类决定实例化哪个类
与其他创作模式比较:
-
设计从使用工厂方法开始 (不那么复杂,可定制,子类增加)并向 Abstract Factory,Prototype 或 Builder 发展 (更灵活,更复杂),因为设计师发现需要更多灵活性的地方
-
抽象工厂类通常使用工厂方法实现,但也可以使用 Prototype 实现 ****
进一步阅读的参考资料:源代码设计模式