记得在设计模式学习的开始遇到一个问题: http://blog.csdn.net/kiritor/article/details/8609105
简单工厂模式在添加新类的时候必须去修改其工厂类,这种方式十分的不好,可以通过工厂方法模式加以改进.
工厂方法模式:
定义一个用于创建对象的一个工厂接口,将对象的创建工作推迟到子类中去,核心的工厂类不在负责
对象的创建而成为一个抽象的工厂角色,只是负责工厂子类必须实现的接口.这样更进一步的抽象使得
在引入新的类的时候,避免了修改工厂角色。从而解决了简单工厂模式中所遇到的问题!
工厂方法模式角色、结构:
● 抽象工厂角色:工厂方法模式的核心,与具体的应用程序无关。任何在该模式下创建对象的工厂类都
必须实现该接口。也可以使用一个抽象类作为与用户交互的接口
● 具体工厂角色:这是实现抽象工厂接口的具体工厂类,包含于应用程序密切相关的逻辑,由应用程序调用
用于创建产品对象。因此它是实现产品扩展的途径,通常与具体产品一一对应的。
● 抽象产品角色:工厂方法模式所创建的对象的基类型,也是产品对象共同的父类或共同拥有的接口,它规
定了产品的相关规范
● 抽象产品角色:实现抽象产品角色所定义的接口,往往与具体工厂角色一一对应。同时他也决定了产品对
象在程序中的与用户交互的方式。
如下图:
工厂方法模式例子:
为了理解工厂方法模式中各个角色之间是如何协作的,以球类运动为例。具体代码如下
产品抽象接口类
package com.kiritor.pattern; public interface Ball { public void play(); }具体产品类
package com.kiritor.pattern; public class BasketBall implements Ball { @Override public void play() { System.out.println("篮球"); } } public class FootBall implements Ball{ @Override public void play() { System.out.println("足球"); } }抽象工厂类:
package com.kiritor.pattern; public interface Factory { public Ball create(); }具体工厂类
package com.kiritor.pattern; public class BasketBallFactory implements Factory{ @Override public Ball create() { // TODO Auto-generated method stub return new BasketBall(); } } public class FootBallFactory implements Factory{ @Override public Ball create() { // TODO Auto-generated method stub return new FootBall(); } }客户端:
package com.kiritor.pattern; public class Test { public static void main(String[] args) { Factory basketballFactory = new BasketBallFactory(); Ball ball = basketballFactory.create(); ball.play(); } }
从上面的代码可以看出,客户端不需要去了解对象的创建过程,也不需要知道创建该对象的是
哪一个工厂,是客户端仅仅处理抽象产品角色提供的接口,让创建实例与使用实例分开。不过工厂
方法模式中,可以将判断逻辑(如何创建对象、创建那个对象)留在抽象工厂角色中,也可在客户
端中将具体工厂角色写死,如果有新的产品对象加入,只需修改具体产品类的角色,对产品类来说符
合开闭原则。但是当产品对象的创建条件改变时,工厂角色必然会修改。因此该模式比不是一劳永
逸的。
附上该模式的类图:
思考:通过动态装在对简单工厂模式进行改良,来达到与工厂模式一样的设计模式(还是略有区别的)
package com.kiritor.pattern; public class Factory2 { public Ball create(String ballName) throws InstantiationException, IllegalAccessException, ClassNotFoundException { Ball ball =(Ball)Class.forName(ballName).newInstance(); return ball; } }
这种简单工厂模式和工厂方法模式有写类似,不必修改具体产品类,但是仍然会存在一些问题:
如果是创建产品的逻辑发生了改变的话,同样必须修改工厂类。