工厂方法模式

来源:互联网 发布:js split 空字符串 编辑:程序博客网 时间:2024/06/04 18:41

前面在简单工厂模式中,举了个例子,说河南人吃面,四川人吃大米。用简单工厂模式,使得我们不再在客户端采用

if判断,或者switch--case来判断创建什么人了。而是将逻辑判断由客户端转移到工厂类中进行判断,使得客户端与我们

真实操作类进行解耦。


当然如果要再新增其他产品类,如山东人,我们只需要修改工厂类与新增一个对应的产品类,再修改下客户端的传参就

可以搞定。虽然客户端的修改减少了,但是对工厂类的修改却增加了,并且违背了开闭原则。我们不仅对扩展开放了,

对修改也开放了。开闭原则所要做到的就是对扩展开放,但是对原有的部分却不做变更,不要修改原有的类。


那么针对这种情况,就有了工厂方法模式。


工厂方法模式:


是一种常用的对象创建型设计模式,此模式的核心精神是封装类中不变的部分,提取其中个性化善变

的部分为独立类,通过依赖注入以达到解耦、复用和方便后期维护拓展的目的。它的核心结构有四个角色,分别是抽

象工厂;具体工厂;抽象产品;具体产品。



抽象工厂

是工厂方法模式的核心,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口。


具体工厂

这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建产

品对象。


抽象产品:

工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。


具体产品:

这个角色实现了抽象产品角色所定义的接口。某具体产品有专门的具体工厂创建,它们之间往往一一对应。


工厂方法模式UML类图:


在这里,我依旧采用前面简单工厂模式中示例,只是要创建一个新的类,山东人




可以看的到上图中,我们对每种人,都创建了一个他们自己的对应的工厂类。那么如果需要新增其他人,只需要创建

对应的人与工厂类即可。对于其他原有的类没有任何改变,符合开闭原则。


工厂方法模式的优点:


1、可以使代码结构清晰,有效地封装变化。在编程中,产品类的实例化有时候是比较复杂和多变的,通过工厂

模式,将产品的实例化封装起来,使得调用者根本无需关心产品的实例化过程,只需依赖工厂即可得到自己想要的产

品。


2、对调用者屏蔽具体的产品类。如果使用工厂模式,调用者只关心产品的接口就可以了,至于具体的实现,调

用者根本无需关心。即使变更了具体的实现,对调用者来说没有任何影响。


3、降低耦合度。产品类的实例化通常来说是很复杂的,它需要依赖很多的类,而这些类对于调用者来说根本无

需知道,如果使用了工厂方法,我们需要做的仅仅是实例化好产品类,然后交给调用者使用。对调用者来说,产品所

依赖的类都是透明的。


代码演示:


首先,我们还是像简单工厂那样定义一个接口,如下:

package fm;/** * 人类 *  * @author Administrator * */public interface Human {public void eat();}



然后,分别定义河南人,四川人去实现这个接口

package fm;/** * 河南人 *  * @author Administrator * */public class HeNanRen implements Human {@Overridepublic void eat() {// TODO Auto-generated method stubSystem.out.println("河南人吃面");}}


package fm;/** * 四川人 *  * @author Administrator * */public class SiChuanRen implements Human {@Overridepublic void eat() {// TODO Auto-generated method stubSystem.out.println("四川人吃大米");}}


然后,我们正式定义工厂方法的核心,用于创建工厂,工厂抽象接口:

package fm;/** * 创建一个工厂类,用于生成其他工厂 *  * @author Administrator * */public interface Factory {public Human createHuman();}



分别创建河南人工厂类,四川人工厂类,实现该接口:

package fm;/** * 河南人工厂类 *  * @author Administrator * */public class HeNanRenFactory implements Factory {@Overridepublic Human createHuman() {// TODO Auto-generated method stubreturn new HeNanRen();}}


package fm;/** * 四川人工厂类 *  * @author Administrator * */public class SiChuanRenFactory implements Factory {@Overridepublic Human createHuman() {// TODO Auto-generated method stubreturn new SiChuanRen();}}




客户端代码:

package fm;public class Test {public static void main(String[] args) {Factory scf = new SiChuanRenFactory();// 如果要修改为河南人时,只需修改此处就可以了Human sc = scf.createHuman();sc.eat();}}



执行后,得到的结果是:四川人吃大米


我们如果要现在新增一个山东人呢?我们只需要新增一个山东人类,新增一个山东人工厂类,即可。对原有的四川

人,河南人,工厂类都没有任何代码上的修改,符合开闭原则。

例外,我们还可以将工厂类统一成一个,然后采用反射来完成产品的创建。

0 0
原创粉丝点击