设计模式-工厂方法
工厂方法(factory method)模式:稍微复杂一点的工厂模式
工厂方法模式,实际上就是:模板方法模式+简单工厂模式 的组合,认为就是简单工厂模式,稍微复杂一点的变种。
场景介绍:
(1) 我们现在要生产的产品有多种;
(2) 每种产品的生产过程,都有一些是共同的逻辑,但是也有一些是特殊的逻辑;
(3) 现在要生产出来各种产品
不用工厂方法模式的代码实现:
首先创建一个类,WithoutFactoryMethodPatternDemo 类,
public class WithoutFactoryMethodPatternDemo{... }
因为我们要生产产品,所以,首先有一个 Product 接口,接口中有一个 execute方法,
public interface Product { void execute(); }
然后,假设我们有3中产品,第一个是静态的Product1,实现Product接口,及接口中的execute方法,其中输出 一句话,代表 产品1的功能逻辑,同样的,还有产品2 和产品3,现在相当于我们有这3种产品。
public static class Product1 implements Product{ public void execute(){ System.out.println("产品1的功能逻辑"); } }
然后的话,如果不用这个 工厂方法模式,我们就用 简单工厂模式 来做,声明一个静态的工厂类 Product1Factory,里面有一个静态的方法createProduct(),返回一个 Product1 的产品,并且它有两个逻辑,分别为 生产产品的通用逻辑 和 生产产品1的特殊逻辑。同样的,还有两个工厂 Product2Factory 和 Product3Factory,除通用逻辑外,也分别执行 生产产品2的特殊逻辑 和 生产产品3的特殊逻辑,并分别返回 Product2 和 Product3.
public static class Product1Factory { public static Product createProduct(){ System.out.println("生产产品的通用逻辑"); System.out.println("生产产品1的特殊逻辑"); return new Product1(); } }
然后,我们在写个main方法,来玩一下。我们先调用Product1的工厂,执行Product1工厂中的execute方法,同样的,然后再是Product2,然后是Product3,
只用 简单工厂模式 的完整代码如下:
public class WithoutFactoryMethodPatternDemo { public static void main(String[] args) { Product product1 = Product1Factory.createProduct(); Product product2 = Product2Factory.createProduct(); Product product3 = Product3Factory.createProduct(); product1.execute(); product2.execute(); product3.execute(); } public interface Product { void execute(); } public static class Product1 implements Product { @Override public void execute() { System.out.println("产品1的功能逻辑"); } } public static class Product2 implements Product { @Override public void execute() { System.out.println("产品2的功能逻辑"); } } public static class Product3 implements Product { @Override public void execute() { System.out.println("产品3的功能逻辑"); } } public static class Product1Factory { public static Product createProduct() { System.out.println("生产产品的通用逻辑"); System.out.println("生产产品1的特殊逻辑"); return new Product1(); } } public static class Product2Factory { public static Product createProduct() { System.out.println("生产产品的通用逻辑"); System.out.println("生产产品2的特殊逻辑"); return new Product2(); } } public static class Product3Factory { public static Product createProduct() { System.out.println("生产产品的通用逻辑"); System.out.println("生产产品3的特殊逻辑"); return new Product3(); } } }
执行main方法,输出如下结果:首先是生产的一个过程,然后生产完了以后是 执行功能的一个过程。
生产产品的通用逻辑
生产产品1的特殊逻辑
生产产品的通用逻辑
生产产品2的特殊逻辑
生产产品的通用逻辑
生产产品3的特殊逻辑
产品1的功能逻辑
产品2的功能逻辑
产品3的功能逻辑
不用 工厂方法模式时 出现的问题
不用 工厂方法模式时,这个有一个什么问题,这个问题在于,其实就是跟那个模板方法模式的问题一模一样。就是多个工厂类中,有这个生产产品的,相同的这个通用逻辑,没有抽取出来,直接复制粘贴放多个工厂里了,如果那段通用逻辑要修改,就需要很麻烦,到所有工厂中去修改代码,可能会忘记修改某个工厂的代码,这样的话,那个工厂生产出来的产品就不符合要求。
比如,Product1Factory中的通用逻辑给它修改了,Product2Factory中的通用逻辑给它修改了,今天就是Product3Factory这给它忘了,那么程序再去跑起来,前面两个,生产产品1 和 生产产品2 的这个通用逻辑,都修改过了,生产产品3 的通用逻辑没有修改,那生产产品3,它就有bug了,所以说,这个肯定是不行的。
应用 工厂方法模式的代码实现:
那我们就来写一个 FactoryMethodPatternDemo,如果要用这个 工厂方法 设计模式的话,应该怎样写的,把没有用模式的实现 WithoutFactoryMethodPatternDemo,在它的基础之上来改,Product1,Product2 和 Product3,这3个产品,以及产品的接口 Product,是不用改变的,主要改的是产品工厂这边。
首先,它需要有 这么一个 静态的抽象工厂类 AbstractProductFactory,定义了 产品(即 继承此抽象类的每个子类) 的生产规范,
public static abstract calss AbstractProductFactory{... }
其中,主要有三个方法,
一个是private修饰的通用的逻辑方法,
private void commonCreate() { System.out.println("生产产品的通用逻辑"); }
一个是protected修饰的 未被实现特殊逻辑方法,
protected abstract Product specificCreate();
一个是public修饰的 整合 通用逻辑 和 特殊逻辑 生产出产品的逻辑方法,返回的是最终的产品对象,
public Product createProduct() { commonCreate(); return specificCreate(); }
然后,所有的产品工厂类,分别继承于此产品工厂抽象类,并分别实现其中的特殊逻辑方法,比如,静态的工厂类 Product1Factory extends AbstractProductFactory,基于 简单工厂模式 Product1Factory 的代码:
public static class Product1Factory { public static Product createProduct(){ System.out.println("生产产品的通用逻辑"); System.out.println("生产产品1的特殊逻辑"); return new Product1(); } }
1.Product1Factory 继承 AbstractProductFactory,并实现其中的 未被实现特殊逻辑方法 specificCreate(),因其在父类中无需供外部调用,所以是非static的;
2.将 简单工厂模式 Product1Factory 中的 createProduct 更名为 specificCreate,去掉static方法声明,去掉其中的通用逻辑,只实现生产产品的特殊逻辑,就可以了:
public static class Product1Factory extends AbstractProductFactory { public Product specificCreate(){ System.out.println("生产产品1的特殊逻辑"); return new Product1(); } }
3.最后,再把它 定义成一个简单的 单例形式,就是把每一个工厂,作为一个单个实例来用,用的是比较简单的单例模式:
声明一个static final的工厂Product1Factory引用,指向 一个 通过自身无参构造器new的实例,并通过 一个get方法,将此实例暴露出去,供外部接口调用此实例。
public static class Product1Factory extends AbstractProductFactory { private static final Product1Factory instance = new Product1Factory(); private Product1Factory() { } public static Product1Factory get() { return instance; } public Product specificCreate(){ System.out.println("生产产品1的特殊逻辑"); return new Product1(); } }
同样的,还有两个工厂 Product2Factory 和 Product3Factory,都继承自 AbstractProductFactory,实现了特殊逻辑方法 specificCreate,分别执行了 生产产品2的特殊逻辑 和 生产产品3的特殊逻辑,并分别返回 Product2 和 Product3.
这样,我们就采用了 类似于模板方法的,这样的一个模式,这个 生产产品的通用逻辑 给它抽到了 一个抽象的工厂父类里面去,在工厂父类里面 放这个通用逻辑,然后,具体生产每个产品 的这个逻辑,交给每个 工厂子类 去实现,然后的话,每个工厂 给它实现成一个 简易的 单例的 这么一个方式。
然后再来看一下,那现在这个代码变成什么样子了。在main方法中,对比 只是用 简单工厂模式 的调用过程,使用 工厂方法模式,我们通过 单例模式 调用 产品工厂 去生产产品,再使用这个产品 调用execute方法 执行 产品的功能逻辑。
Product product1 = Product1Factory.get().createProduct();
同样的,还有 Product2 和 Product3,然后,我们分别执行一下它们的execut方法,输出一下结果,ok。
main方法,代码如下:
public static void main(String[] args) { /* Product product1 = Product1Factory.createProduct(); Product product2 = Product2Factory.createProduct(); Product product3 = Product3Factory.createProduct(); product1.execute(); product2.execute(); product3.execute(); */ Product product1 = Product1Factory.get().createProduct(); Product product2 = Product2Factory.get().createProduct(); Product product3 = Product3Factory.get().createProduct(); product1.execute(); product2.execute(); product3.execute(); }
使用 工厂方法模式 的完整代码如下:
public class FactoryMethodPatternDemo { public static void main(String[] args) { /* Product product1 = Product1Factory.createProduct(); Product product2 = Product2Factory.createProduct(); Product product3 = Product3Factory.createProduct(); product1.execute(); product2.execute(); product3.execute(); */ Product product1 = Product1Factory.get().createProduct(); Product product2 = Product2Factory.get().createProduct(); Product product3 = Product3Factory.get().createProduct(); product1.execute(); product2.execute(); product3.execute(); } public interface Product { void execute(); } public static class Product1 implements Product { @Override public void execute() { System.out.println("产品1的功能逻辑"); } } public static class Product2 implements Product { @Override public void execute() { System.out.println("产品2的功能逻辑"); } } public static class Product3 implements Product { @Override public void execute() { System.out.println("产品3的功能逻辑"); } } public static abstract class AbstractProductFactory { public Product createProduct() { commonCreate(); return specificCreate(); } private void commonCreate() { System.out.println("生产产品的通用逻辑"); } protected abstract Product specificCreate(); } public static class Product1Factory extends AbstractProductFactory { private static final Product1Factory instance = new Product1Factory(); private Product1Factory() { } public static Product1Factory get() { return instance; } public Product specificCreate() { System.out.println("生产产品1的特殊逻辑"); return new Product1(); } } public static class Product2Factory extends AbstractProductFactory{ private static final Product2Factory instance = new Product2Factory(); private Product2Factory() { } public static Product2Factory get() { return instance; } public Product specificCreate() { System.out.println("生产产品2的特殊逻辑"); return new Product2(); } } public static class Product3Factory extends AbstractProductFactory{ private static final Product3Factory instance = new Product3Factory(); private Product3Factory() { } public static Product3Factory get() { return instance; } public Product specificCreate() { System.out.println("生产产品3的特殊逻辑"); return new Product3(); } } }
那我们来看一下,执行main方法,输出如下结果:生产产品的通用逻辑,特殊逻辑,执行这个功能,对吧!
生产产品的通用逻辑
生产产品1的特殊逻辑
生产产品的通用逻辑
生产产品2的特殊逻辑
生产产品的通用逻辑
生产产品3的特殊逻辑
产品1的功能逻辑
产品2的功能逻辑
产品3的功能逻辑
使用工厂方法模式的好处:
那使用 工厂方法模式,这个好处就是说,我们把每个工厂里面,生产产品的 一个通用逻辑 给抽到了一个,抽象的这个工厂里面来,比如说现在,我们要把生产产品的通用逻辑,把它给改一下,那么只修改一个地方就可以了。
private void commonCreate() { System.out.println("生产产品的通用逻辑,修改"); }
执行输出一下结果,如下:
生产产品的通用逻辑,修改
生产产品1的特殊逻辑
生产产品的通用逻辑,修改
生产产品2的特殊逻辑
生产产品的通用逻辑,修改
生产产品3的特殊逻辑
产品1的功能逻辑
产品2的功能逻辑
产品3的功能逻辑
那么,就不涉及到说,通用逻辑修改,要把每个工厂里面的代码,都要去修改,其实综上可以看到,这个就是把 简单工厂,跟那个 模板方法 给结合到了一起而已。
工厂方法模式的实际应用场景:
那么,这个模式实际上用的是比较少的,用的并不多,它针对的是说,对 工厂模式 做一个改良。那么我们实战 是在电商项目里面,结合后面的一个命令名模式,然后,再结合电商的一个业务,来演示说,这个 工厂方法 这个模式,跟 命令模式 结合在一起,然后,怎么去设计电商业务的这一块代码。