💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
## [接口和工厂方法模式](https://lingcoder.gitee.io/onjava8/#/book/10-Interfaces?id=%e6%8e%a5%e5%8f%a3%e5%92%8c%e5%b7%a5%e5%8e%82%e6%96%b9%e6%b3%95%e6%a8%a1%e5%bc%8f) 接口是多实现的途径,而生成符合某个接口的对象的典型方式是*工厂方法*设计模式。不同于直接调用构造器,只需调用工厂对象中的创建方法就能生成对象的实现——理论上,通过这种方式可以将接口与实现的代码完全分离,使得可以透明地将某个实现替换为另一个实现。这里是一个展示工厂方法结构的例子: ~~~ // interfaces/Factories.java interface Service { void method1(); void method2(); } interface ServiceFactory { Service getService(); } class Service1 implements Service { Service1() {} // Package access @Override public void method1() { System.out.println("Service1 method1"); } @Override public void method2() { System.out.println("Service1 method2"); } } class Service1Factory implements ServiceFactory { @Override public Service getService() { return new Service1(); } } class Service2 implements Service { Service2() {} // Package access @Override public void method1() { System.out.println("Service2 method1"); } @Override public void method2() { System.out.println("Service2 method2"); } } class Service2Factory implements ServiceFactory { @Override public Service getService() { return new Service2(); } } 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 Service1Factory()); // Services are completely interchangeable: serviceConsumer(new Service2Factory()); } } ~~~ 输出: ~~~ Service1 method1 Service1 method2 Service2 method1 Service2 method2 ~~~ 如果没有工厂方法,代码就必须在某处指定将要创建的**Service**的确切类型,从而调用恰当的构造器。 为什么要添加额外的间接层呢?一个常见的原因是创建框架。假设你正在创建一个游戏系统;例如,在相同的棋盘下国际象棋和西洋跳棋: ~~~ // interfaces/Games.java // A Game framework using Factory Methods interface Game { boolean move(); } interface GameFactory { Game getGame(); } class Checkers implements Game { private int moves = 0; private static final int MOVES = 3; @Override public boolean move() { System.out.println("Checkers move " + moves); return ++moves != MOVES; } } class CheckersFactory implements GameFactory { @Override public Game getGame() { return new Checkers(); } } class Chess implements Game { private int moves = 0; private static final int MOVES = 4; @Override public boolean move() { System.out.println("Chess move " + moves); return ++moves != MOVES; } } class ChessFactory implements GameFactory { @Override 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()); } } ~~~ 输出: ~~~ Checkers move 0 Checkers move 1 Checkers move 2 Chess move 0 Chess move 1 Chess move 2 Chess move 3 ~~~ 如果类**Games**表示一段很复杂的代码,那么这种方式意味着你可以在不同类型的游戏里复用这段代码。你可以再想象一些能够从这个模式中受益的更加精巧的游戏。 在下一章,你将会看到一种更加优雅的使用匿名内部类的工厂实现方式。