更多的关于工厂方法设计模式的内容请移步:http://www.cnblogs.com/chenssy/archive/2013/05/24/3096161.html;
首先我们来了解一下面向对象设计的几个原则:
(1)OCP原则:(open-closed principle)又叫做开闭原则。一个软件的实体应当对拓展开放,对修改关闭。通俗的讲就是,当我们在增加新的功能的时候,应该尽可能地通过增加新的类来增加新的功能,而不是在原有的类的基础上进行修改。这是要注意的。
(2)依赖倒转原则DIP(Dependence Inverse Principle):在以后的编程的过程当中,我们应当尽可能地面向接口编程,而不是面向实现的编程。举一个例子来说明就是:比如我们有来个类,A类和B类。我们有一个方法就是在B类中调用A类,那么B和A之间的依赖关系就很强了。但是,如果我们规定,A类B类都必须实现各自的接口的话,我们就可以减弱A和B之间的依赖关系。从而将面向实现编程转化为面向接口编程。
(3)迪米特法则(LOD:Law of Demeter):只与朋友之间进行通信,而不是与陌生人之间进行通信。这是什么意思呢?比如我们有一个类A,我们尽可能地避免A和其它的类发生关系。这有利于A的解耦。如果一个类其它的很多的类都发生了关系,那么以后对这个类的功能的拓展就会产生不利影响。这是要注意的。其实这些和我们的社会关系都是互相对象的。我们的社会其实就是一个讲究“分工”与“合作”的社会。只有分工明确了,我们的社会才能更好的发展。
/*接口是实现多重继承的重要的途径,而生成遵循某个接口的对象的典型的方式是工厂方法设计模式。这与直接调用 * 构造器不同。我们在工厂对象上调用是创建的方法,而该工厂对象将生成接口的某个可以实现的对象。理论上 * 通过这种方式,我们的代码将完全与接口的实现分离。这就使我们可以透明地将某个实现替换为另外的一个实现 * */ interface Service{ void method1(); void method2(); } interface ServiceFactory{ // 调用的是创建方法 Service getService(); } //实现接口的一个对象 class Implementation1 implements Service{ Implementation1(){} @Override public void method1() { System.out.println("Implementation1 method1"); } @Override public void method2() { System.out.println("Implementation1 method2"); } } //工厂生成对象 class Implementation1Factory implements ServiceFactory{ @Override public Service getService() { return new Implementation1(); } } class Implementation2 implements Service{ Implementation2(){} @Override public void method1() { System.out.println("Implementation2 method1"); } @Override public void method2() { System.out.println("Implementation2 method2"); } } class Implementation2Factory implements ServiceFactory{ @Override 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()); serviceConsumer(new Implementation2Factory()); }}
最后的输出的结果为:
Implementation1 method1 Implementation1 method2 Implementation2 method1 Implementation2 method2
为什么我们想要添加这种级别的间接性呢?一个常见的原因是想要创建框架。假设你正在创建一个对弈游戏系统,例如在相同的棋盘上下国际象棋和西洋跳棋。程序如下:
interface Game{ boolean move(); } interface GameFactory{ Game getGame(); } class Checkers implements Game{ private int moves; private static final int MOVES=3; @Override public boolean move() { System.out.println("Checkers move" + moves); return ++moves!=MOVES; } } class CheckerFactory implements GameFactory{ @Override public Game getGame() { return new Checkers(); } } class Chess implements Game{ private int moves=0; private static final int MOVE=4; @Override public boolean move() { System.out.println("Chess move" + moves); return ++moves!=MOVE; } } 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 CheckerFactory()); playGame(new ChessFactory()); } }程序运行的结果为:Checkers move0
Checkers move1
Checkers move2
Chess move0
Chess move1
Chess move2
Chess move3其实,如果使用了匿名内部类的创建的方式,你就可以看到更加优雅的工厂的实现的模式。代码如下:
/*在本例中,一般情况下,我们只需要创建单一的工厂对象,因此在本例中它被创建为Service实现中的一个static域。 * */ interface Service{ void method1(); void method2(); } interface ServiceFactory{ // 调用的是创建方法 Service getService(); } //实现接口的一个对象 class Implementation1 implements Service{ // 将构造器私有化,防止外部进行创建对象 private Implementation1(){} @Override public void method1() { System.out.println("Implementation1 method1"); } @Override public void method2() { System.out.println("Implementation1 method2"); } //创建了一个匿名内部类:并且这个域是使用了static 来进行修饰的。用static来进行修饰的域 // 只会被加载一次。 public static ServiceFactory factory=new ServiceFactory(){ @Override public Service getService() { return new Implementation1(); } }; } class Implementation2 implements Service{ // 将构造器私有化,防止外部创建对象。 private Implementation2(){} @Override public void method1() { System.out.println("Implementation2 method1"); } @Override public void method2() { System.out.println("Implementation2 method2"); } public static ServiceFactory factory=new ServiceFactory() { @Override 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); serviceConsumer(Implementation2.factory); } }对于另外的一个程序,也可以使用匿名内部类来进行创建:/*如果Games表示的是一段很复杂的内容,那么这种方式允许你在不同类型的游戏中服用这段代码*/ interface Game{ boolean move(); } interface GameFactory{ Game getGame(); } class Checkers implements Game{ private Checkers(){} private int moves; private static final int MOVES=3; @Override public boolean move() { System.out.println("Checkers move" + moves); return ++moves!=MOVES; } public static GameFactory factory=new GameFactory() { @Override public Game getGame() { return new Checkers(); } }; } class Chess implements Game{ private int moves=0; private static final int MOVE=4; @Override public boolean move() { System.out.println("Chess move" + moves); return ++moves!=MOVE; } public static GameFactory factory=new 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(Checkers.factory); playGame(Chess.factory); } }其实,在这里我还想补充的一点就是:当使用工厂化方法来创建对象的时候,我们一般是不关心对象是如何被创建的。只要你 传入合适的参数,那么我们就可以创建对象。但是,需要创建的类比较多的时候,那么这个类就显得有点复杂了,并且难于维护了。这是要注意。这个工厂方法设计模式与简单工床模式相比,虽然前符合了OCP原则,但是可以明显看出前者需要的类比后面的简单工厂模式的类要多。所以在类的数量很多的时候,那么这个体系显得难免就有些复杂了。这是要注意的。其实在一般的项目开发当中,我们一般会使用简单工厂模式。
最后我们来看一下工厂方法模式和简单工厂模式之间的区别:
主要是从结构复杂度,代码复杂度,还有客户端管理复杂度来进行比较: