前言
上一篇文章讲述了简单工厂模式,其实简单工厂模式也算是工厂方法模式的其中一种,简单工厂模式的最大优点工厂中集成了必要的逻辑判断,根据客户端的选择动态的生成实例化类。从而去除与具体产品的依赖性。但是工厂方法中承载了太多的功能,当有新的需求就需要在工厂中添加新的case判断语句。违背了“开闭原则”(对扩展开放,对修改关闭)。
一、工厂方法模式的含义
含义:将尽量长的代码分割成为小段代码然后封装,从而减少每段代码之间的耦合。操作起来就是定义一个用于创建对象的接口,让子类决定实例化哪个类对象,就是让一个产品类的实例化延迟到其工厂的子类进行。
1.UML图关系展示
2.工厂方法模式细节代码演示
这里笔者使用健身相关概念进行解释,为了便于区分直接使用拼音作为类名
1.首先定义抽象类----手臂训练类
package com.shuyixiao.工厂方法模式; /** * @author 舒一笑 * @date 2023/4/28 */ public abstract class shoubixunlianlei { public String doTraining(){ System.out.println("手臂训练类"); return "手臂训练类"; } }
2.分别将手臂训练类的五个子类分别实现
package com.shuyixiao.工厂方法模式; /** * @author 舒一笑 * @date 2023/4/28 */ public class yalingertouwanjulei extends shoubixunlianlei{ @Override public String doTraining() { System.out.println("我做哑铃二头弯举训练"); return super.doTraining(); } }
package com.shuyixiao.工厂方法模式; /** * @author 舒一笑 * @date 2023/4/28 */ public class shengsuowanjulei extends shoubixunlianlei{ @Override public String doTraining() { System.out.println("我做绳索弯举训练"); return super.doTraining(); } }
package com.shuyixiao.工厂方法模式;/** * * @author 舒一笑 * @date 2023/4/28 */public class shengsuobiqushenlei extends shoubixunlianlei{ @Override public String doTraining() { System.out.println("我做绳索臂屈伸类训练"); return super.doTraining(); } }
package com.shuyixiao.工厂方法模式; /** * @author 舒一笑 * @date 2023/4/28 */ public class yalingwanjuchaojizulei extends shoubixunlianlei{ @Override public String doTraining() { System.out.println("我做哑铃弯举超级组训练"); return super.doTraining(); } }
package com.shuyixiao.工厂方法模式; /** * @author 舒一笑 * @date 2023/4/28 */ public class shengsuowanjuchaojizulei extends shoubixunlianlei{ @Override public String doTraining() { System.out.println("我做绳索弯举超级组训练"); return super.doTraining(); } }
3.定义训练工厂接口
package com.shuyixiao.工厂方法模式; /** * @author 舒一笑 * @date 2023/4/28 */ public interface xunliangongchangjiekou { shoubixunlianlei getInstance(); }
4.分别在具体各自的工厂(基础训练和进阶训练完成对象创建)
package com.shuyixiao.工厂方法模式; /** * @author 舒一笑 * @date 2023/4/28 */ public class jichushoubixunliangongchang implements xunliangongchangjiekou{ @Override public shoubixunlianlei getInstance() { return new shengsuobiqushenlei(); } }
package com.shuyixiao.工厂方法模式; /** * @author 舒一笑 * @date 2023/4/28 */ public class jinjieshoubixunliangongchang implements xunliangongchangjiekou{ @Override public shoubixunlianlei getInstance() { return new shengsuowanjuchaojizulei(); } }
5.客户端的调用
package com.shuyixiao.工厂方法模式; /** * @author 舒一笑 * @date 2023/4/28 */ public class Shuyixiao { public static void main(String[] args) { jichushoubixunliangongchang jichushoubixunliangongchang = null; shoubixunlianlei instance = jichushoubixunliangongchang.getInstance(); String s = instance.doTraining(); System.out.println("s = " + s); } }
二、工厂方法模式的总结
1.主要角色
抽象工厂:提供创建产品的接口,调用者通过访问它具体工厂的方法来创建产品,上述中就是使用训练工厂接口来当作抽象工厂,定义了getInstance()方法获取对象实例
具体工厂:实现抽象工厂中的抽象方法,完成对具体产品的创建,上述例子中就是基础手臂训练工厂和进阶手臂训练工厂,实现对自己类的创建
抽象产品:定义了产品的规范,描述了产品的功能和主要特性,上述例子中定义了手臂训练类作为抽象产品
具体产品:实现了抽象产品角色定义的接口或者继承某个抽象类作为父类,并重写其中的方法完成对具体产品的定义,上述代码中则是五个各自的手臂训练计划类。
2.优缺点分析
优点:
- 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程;
- 在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则;
缺点:
- 每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度。
3.使用场景
- 需要使用很多重复代码创建对象时,比如,DAO 层的数据对象、API 层的 VO 对象等。
- 创建对象要访问外部信息或资源时,比如,读取数据库字段,获取访问授权 token 信息,配置文件等。
- 创建需要统一管理生命周期的对象时,比如,会话信息、用户网页浏览轨迹对象等。
- 创建池化对象时,比如,连接池对象、线程池对象、日志对象等。这些对象的特性是:有限、可重用,使用工厂方法模式可以有效节约资源。
- 希望隐藏对象的真实类型时,比如,不希望使用者知道对象的真实构造函数参数等。