ThinkInJava中的接口与工厂

来源:互联网 发布:录制屏幕的软件 编辑:程序博客网 时间:2024/06/05 13:30

接口是实现多重继承的途径,而生成遵循某个接口的对象的典型方式就是工厂方法设计模式.

这与直接调用构造器不同,我们在工厂对象上调用的是创建方法,而该工厂对象将生成接口的某个实现的对象.

理论上,通过这方式,我们的代码将完全与接口的实现分离,这就使得我们可以透明的将某个实现替换为另一个实现.

下面的代码实例展示了工厂方法的结构:

//: interfaces/Factories.javaimport static net.mindview.util.Print.*;interface Service {  void method1();  void method2();}interface ServiceFactory {  Service getService();}class Implementation1 implements Service {  Implementation1() {} // Package access  public void method1() {print("Implementation1 method1");}  public void method2() {print("Implementation1 method2");}}class Implementation1Factory implements ServiceFactory {  public Service getService() {    return new Implementation1();  }}class Implementation2 implements Service {  Implementation2() {} // Package access  public void method1() {print("Implementation2 method1");}  public void method2() {print("Implementation2 method2");}}class Implementation2Factory implements ServiceFactory {  public Service getService() {    return new Implementation2();  }}public class Factories {  public static void serviceConsumer(ServiceFactory fact) {    Service s = fact.getService();    s.method1();    s.method2();  }  public static void main(String[] args) {    serviceConsumer(new Implementation1Factory());    // Implementations are completely interchangeable:    serviceConsumer(new Implementation2Factory());  }} /* Output:Implementation1 method1Implementation1 method2Implementation2 method1Implementation2 method2*///:~


package net.mindview.util;import java.io.*;public class Print {  // Print with a newline:  public static void print(Object obj) {    System.out.println(obj);  }  // Print a newline by itself:  public static void print() {    System.out.println();  }  // Print with no line break:  public static void printnb(Object obj) {    System.out.print(obj);  }  // The new Java SE5 printf() (from C):  public static PrintStream  printf(String format, Object... args) {    return System.out.printf(format, args);  }} ///:~

如果不是工厂方法,你的代码就必须在某处指定将要创建的Service的确切类型,以便调用合适的构造器.

为什么我们想要添加这种额外级别的间接性呢? 一个常见的原因是想要创建框架:

假设你正在创建一个对弈游戏系统, 例如,在相同的棋盘上下国际象棋和跳棋: 

//: interfaces/Games.java// A Game framework using Factory Methods.import static net.mindview.util.Print.*;interface Game { boolean move(); }interface GameFactory { Game getGame(); }class Checkers implements Game {  private int moves = 0;  private static final int MOVES = 3;  public boolean move() {    print("Checkers move " + moves);    return ++moves != MOVES;  }}class CheckersFactory implements GameFactory {  public Game getGame() { return new Checkers(); }}class Chess implements Game {  private int moves = 0;  private static final int MOVES = 4;  public boolean move() {    print("Chess move " + moves);    return ++moves != MOVES;  }}class ChessFactory implements GameFactory {  public Game getGame() { return new Chess(); }}public class Games {  public static void playGame(GameFactory factory) {    Game s = factory.getGame();    while(s.move())      ;  }  public static void main(String[] args) {    playGame(new CheckersFactory());    playGame(new ChessFactory());  }} /* Output:Checkers move 0Checkers move 1Checkers move 2Chess move 0Chess move 1Chess move 2Chess move 3*///:~
如果Game类表示一段复杂的代码,那么这种方式就允许你在不同类型的游戏中复用这段代码,你可以再想象一些能够从这个模式中受益的更加精巧的游戏.

更优雅的工厂实现方式,是使用匿名内部类;

//: innerclasses/Factories.javaimport static net.mindview.util.Print.*;interface Service {  void method1();  void method2();}interface ServiceFactory {  Service getService();}class Implementation1 implements Service {  private Implementation1() {}  public void method1() {print("Implementation1 method1");}  public void method2() {print("Implementation1 method2");}  public static ServiceFactory factory =    new ServiceFactory() {      public Service getService() {        return new Implementation1();      }    };}class Implementation2 implements Service {  private Implementation2() {}  public void method1() {print("Implementation2 method1");}  public void method2() {print("Implementation2 method2");}  public static ServiceFactory factory =    new ServiceFactory() {      public Service getService() {        return new Implementation2();      }    };}public class Factories {  public static void serviceConsumer(ServiceFactory fact) {    Service s = fact.getService();    s.method1();    s.method2();  }  public static void main(String[] args) {    serviceConsumer(Implementation1.factory);    // Implementations are completely interchangeable:    serviceConsumer(Implementation2.factory);  }} /* Output:Implementation1 method1Implementation1 method2Implementation2 method1Implementation2 method2*///:~
现在用于Implementation1 和Implementation2的构造器都可以是私有的,并且没有任何必要去创建作为工厂的具名类.

另外,你经常只需要单一的工厂对象,因此在本实例中它被创建为Service实现中的一个static域,这样产生语法也更具实际意义

Games用匿名内部类改造:

//: innerclasses/Games.java// Using anonymous inner classes with the Game framework.import static net.mindview.util.Print.*;interface Game { boolean move(); }interface GameFactory { Game getGame(); }class Checkers implements Game {  private Checkers() {}  private int moves = 0;  private static final int MOVES = 3;  public boolean move() {    print("Checkers move " + moves);    return ++moves != MOVES;  }  public static GameFactory factory = new GameFactory() {    public Game getGame() { return new Checkers(); }  };}class Chess implements Game {  private Chess() {}  private int moves = 0;  private static final int MOVES = 4;  public boolean move() {    print("Chess move " + moves);    return ++moves != MOVES;  }  public static GameFactory factory = new GameFactory() {    public Game getGame() { return new Chess(); }  };}public class Games {  public static void playGame(GameFactory factory) {    Game s = factory.getGame();    while(s.move())      ;  }  public static void main(String[] args) {    playGame(Checkers.factory);    playGame(Chess.factory);  }} /* Output:Checkers move 0Checkers move 1Checkers move 2Chess move 0Chess move 1Chess move 2Chess move 3*///:~


4 0
原创粉丝点击