工厂方法模式
2016-05-22 15:47
344 查看
前面在简单工厂模式中,举了个例子,说河南人吃面,四川人吃大米。用简单工厂模式,使得我们不再在客户端采用
if判断,或者switch--case来判断创建什么人了。而是将逻辑判断由客户端转移到工厂类中进行判断,使得客户端与我们
真实操作类进行解耦。
当然如果要再新增其他产品类,如山东人,我们只需要修改工厂类与新增一个对应的产品类,再修改下客户端的传参就
可以搞定。虽然客户端的修改减少了,但是对工厂类的修改却增加了,并且违背了开闭原则。我们不仅对扩展开放了,
对修改也开放了。开闭原则所要做到的就是对扩展开放,但是对原有的部分却不做变更,不要修改原有的类。
那么针对这种情况,就有了工厂方法模式。
工厂方法模式:
是一种常用的对象创建型设计模式,此模式的核心精神是封装类中不变的部分,提取其中个性化善变
的部分为独立类,通过依赖注入以达到解耦、复用和方便后期维护拓展的目的。它的核心结构有四个角色,分别是抽
象工厂;具体工厂;抽象产品;具体产品。
抽象工厂:
是工厂方法模式的核心,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口。
具体工厂:
这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建产
品对象。
抽象产品:
工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。
具体产品:
这个角色实现了抽象产品角色所定义的接口。某具体产品有专门的具体工厂创建,它们之间往往一一对应。
工厂方法模式UML类图:
在这里,我依旧采用前面简单工厂模式中示例,只是要创建一个新的类,山东人
可以看的到上图中,我们对每种人,都创建了一个他们自己的对应的工厂类。那么如果需要新增其他人,只需要创建
对应的人与工厂类即可。对于其他原有的类没有任何改变,符合开闭原则。
工厂方法模式的优点:
1、可以使代码结构清晰,有效地封装变化。在编程中,产品类的实例化有时候是比较复杂和多变的,通过工厂
模式,将产品的实例化封装起来,使得调用者根本无需关心产品的实例化过程,只需依赖工厂即可得到自己想要的产
品。
2、对调用者屏蔽具体的产品类。如果使用工厂模式,调用者只关心产品的接口就可以了,至于具体的实现,调
用者根本无需关心。即使变更了具体的实现,对调用者来说没有任何影响。
3、降低耦合度。产品类的实例化通常来说是很复杂的,它需要依赖很多的类,而这些类对于调用者来说根本无
需知道,如果使用了工厂方法,我们需要做的仅仅是实例化好产品类,然后交给调用者使用。对调用者来说,产品所
依赖的类都是透明的。
代码演示:
首先,我们还是像简单工厂那样定义一个接口,如下:
然后,分别定义河南人,四川人去实现这个接口
然后,我们正式定义工厂方法的核心,用于创建工厂,工厂抽象接口:
分别创建河南人工厂类,四川人工厂类,实现该接口:
客户端代码:
执行后,得到的结果是:四川人吃大米
我们如果要现在新增一个山东人呢?我们只需要新增一个山东人类,新增一个山东人工厂类,即可。对原有的四川
人,河南人,工厂类都没有任何代码上的修改,符合开闭原则。
例外,我们还可以将工厂类统一成一个,然后采用反射来完成产品的创建。
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 { @Override public void eat() { // TODO Auto-generated method stub System.out.println("河南人吃面"); } }
package fm; /** * 四川人 * * @author Administrator * */ public class SiChuanRen implements Human { @Override public void eat() { // TODO Auto-generated method stub System.out.println("四川人吃大米"); } }
然后,我们正式定义工厂方法的核心,用于创建工厂,工厂抽象接口:
package fm; /** * 创建一个工厂类,用于生成其他工厂 * * @author Administrator * */ public interface Factory { public Human createHuman(); }
分别创建河南人工厂类,四川人工厂类,实现该接口:
package fm; /** * 河南人工厂类 * * @author Administrator * */ public class HeNanRenFactory implements Factory { @Override public Human createHuman() { // TODO Auto-generated method stub return new HeNanRen(); } }
package fm; /** * 四川人工厂类 * * @author Administrator * */ public class SiChuanRenFactory implements Factory { @Override public Human createHuman() { // TODO Auto-generated method stub return new SiChuanRen(); } }
客户端代码:
package fm; public class Test { public static void main(String[] args) { Factory scf = new SiChuanRenFactory();// 如果要修改为河南人时,只需修改此处就可以了 Human sc = scf.createHuman(); sc.eat(); } }
执行后,得到的结果是:四川人吃大米
我们如果要现在新增一个山东人呢?我们只需要新增一个山东人类,新增一个山东人工厂类,即可。对原有的四川
人,河南人,工厂类都没有任何代码上的修改,符合开闭原则。
例外,我们还可以将工厂类统一成一个,然后采用反射来完成产品的创建。
相关文章推荐
- sax 解析 xml
- 谈一谈.net析构函数对垃圾回收的影响
- 16色工具栏
- 多项式求和
- Git在另一个电脑上创建仓库并向远程仓库提交代码
- Linux查找命令find与文件三种时间
- JobScheduler内幕实现和深度思考(第七篇)
- 第13课:Spark Streaming 源码解读之Driver 容错安全性
- 一个帮助编辑,测试Cron表达式的网站
- 样本归一化
- shell常用命令
- 图片验证码技术
- jQuery load()方法的封装
- Java HashMap的工作原理
- C语言实现直接法解线性方程组
- 大数的四则运算与比较
- docker进入容器的方式
- 努力安放这颗好强而骄傲的心
- 一条SQL的改写
- R语言 关联规则(二)