接口与工厂
接口是实现多重继承的途径,而生成遵循某个接口的对象的典型方式就是工厂设计模式。这与直接调用构造器不同,我们在工厂对象上调用的是创建方法,而该工厂对象将生成接口的某个实现的对象。理论上,通过这种方式,我们的代码将完全与接口的实现分离。使我们可以透明地将某个实现替换为另一个实现。
interface Service{
void method1();
void method2();
}
interface ServiceFatory{
Service getService();
}
class Implementation1 implements Service{
Implementation1(){} //包访问权限
public void method1(){
System.out.println("Implementation1 method1");
}
public void method2(){
System.out.println("Implementation1 method2");
}
}
class Implementation1Factory implements ServiceFatory{
public Service getService(){
return new Implementation1();
}
}
class Implementation2 implements Service{
Implementation2(){}
public void method1(){
System.out.println("Implementation2 method1");
}
public void method2(){
System.out.println("Implementation2 method2");
}
}
class Implementation2Fatory implements ServiceFatory{
public Service getService(){
return new Implementation2();
}
}
public class Factories {
public static void serviceConsumer(ServiceFatory fact){
Service s = fact.getService();
s.method1();
s.method2();
}
public static void main(String[] args){
serviceConsumer(new Implementation1Factory());
serviceConsumer(new Implementation2Fatory());
}
}
为什么要添加这种额外级别的间接性?一个常见的原因就是想要创建框架,假设你正在创建一个对弈游戏系统,在相同的棋盘上下国际象棋和跳棋
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(){
System.out.println("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(){
System.out.println("Chess move " + moves);
return ++moves != MOVES;
}
}
class ChessFactory implements GameFactory{
public Game getGame(){
return new Chess();
}
}
public class Games {
public static void playGame(GameFactory gameFactory){
Game s = gameFactory.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
总结
“确定接口是理想选择,因而应该总是选择接口而不是具体的类”,这其实是一种引诱。
恰当的原则应该是优先选择类而不是接口,从类开始,如果接口的必需性变得非常明确,那么就进行重构。