工厂模式详解
简述
工厂模式是Java最常用的设计模式之一,这种模式属于创建型模式,提供了一种创建对象的最佳模式。它并不是一个独立的设计模式,而是三种功能接近的设计模式的统称,分别是简单工厂模式,工厂方法模式,抽象工厂模式。
案例引入
当我们实例化一个对象的时候,一般我们直接使用new关键字,但我们有没有想到如果创建对象需要一系列复杂的初始化过程,我们就要在对象的构造函数写很长很长的代码,大大降低了程序的可读性,同时也可能导致程序的耦合度较高,这里就可以提到我们的工厂模式了。
简单工厂模式
我们在实例化对象的时候,不使用new关键字,而是交由一个新的类,叫工厂类创建。
我们来看一个例子,在我们的业务代码中,有个被广泛引用的“口罩”类,这里类实例需要在许多地方被创建和初始化,且初始化的代码较为复杂。
public class Mask { //构造函数 public Mask(){ // ..... // 100行初始化代码 } }
此时我们就可以新建一个口罩工厂类,用于实例化口罩类,把初始化代码搬进工厂里面。
public class MaskFactory { public Mask createMask() { Mask mask = new Mask(); // ..... // 100行初始化代码 return mask; } }
如果口罩类存在子类,可以是继承,可以是接口
我们就根据输入的参数来决定生产出哪种产品
像这样通过工厂类创建对象,且根据传入的参数决定具体子类对象的做法,就是简单工厂模式。
工厂方法模式
但若我们需要新加新的口罩子类,口罩工厂的创建方法中就需要新增新的if-else判断,这样就不符合面向对象的开放-封闭原则。
所谓面向对象的开放-封闭原则,就是在程序中对“扩展”开放,对“修改”封闭。如果每次业务改动都要增加新的if-else,就涉及对旧有代码的修改,不但容易出错,可读性也不好。
想要解决这个问题,我们可以为每个口罩子类创建对应的工厂子类,这些工厂子类分别实现抽象的工厂接口。这样一来,我们只需实例化不同的工厂子类,调用创建方法,得到的就是对应的口罩对象,这背后是面向对象的多态特性。
根据这个思路,我们重构一下工厂,现在工厂是个接口,抽象方法是createMask。
然后工厂有两个子类——高端口罩工厂和低端口罩工厂
他们实现了createMask方法
在代码中,工厂类变成了抽象的接口,高端口罩工厂和低端口罩工厂这两个子类分别实现了这两个接口。
在客户端,想要创建什么口罩对象,只需要实例化不同的工厂子类,然后调用他们的创建方法即可,无需再传入参数。
像这样每一个口罩子类都对应一个工厂子类,利用多态性质动态创建对象的模式,就是工厂方法模式。
抽象工厂模式
如果业务中我们要创建口罩,防毒面具,防护服三种产品,且每一种产品都包含高端到低端两类,如果按照工厂方法模式创建工厂子类,就如下图所示:
当产品数量很多的时候,工厂类的数量也会越来越多,搞得非常复杂。
那该怎么办呢——我们不需要为每一个产品配置一个工厂,而是可以把这些产品进行分组。对于上面的例子我们可以分成高端组和低端组,由同一个工厂类的不同方法创建。
我们以口罩和防护服举例,他们是两个接口,分别由高端和低端两个实现类:
public interface IMask { void showMask(); } public class LowEndMask implements IMask { @Override public void showMask(){ System.out.println("我的低端口罩"); } } public class HighEndMask implements IMask { @Override public void showMask() { System.out.println("我是高端口罩"); } } public interface IProtectiveSuit { void showSuit(); } public class LowEndProtectiveSuit implements IProtectiveSuit { @Override public void showSuit() { System.out.println("我是低端防护服"); } } public class HighEndProtectiveSuit implements IProtectiveSuit { @Override public void showSuit() { System.out.println("我是高端防护服"); } }
然后是工厂类,因为产品分成了高端和低端两个组,工厂也就分成了高端工厂和低端工厂,各自负责组内产品的创建:
public interface IFactory { //创建口罩 IMask createMask(); //创建防护服 IProtectiveSuit createSuit(); } public class LowEndFactory implements IFactory { @Override public IMask createMask() { IMask mask = new LowEndMask(); // ..... // LowEndMask的100行初始化代码 return mask; } @Override public IProtectiveSuit createSuit() { IProtectiveSuit suit = new LowEndProtectiveSuit(); // ..... // LowEndProtectiveSuit的100行初始化代码 return suit; } } public class HighEndFactory implements IFactory { @Override public IMask createMask() { IMask mask = new HighEndMask(); // ..... // HighEndMask的100行初始化代码 return mask; } @Override public IProtectiveSuit createSuit() { IProtectiveSuit suit = new HighEndProtectiveSuit(); // ..... // HighEndProtectiveSuit的100行初始化代码 return suit; } }
然后我们写test类,通过实例化不同工厂子类,调用不同创建方法,就可以创建出不同的产品:
像这样把产品分组,组内不同的产品对应同一工厂的不同方法的设计模式,就叫做抽象工厂模式。
总结
•简单工厂模式有唯一的工厂类,工厂类的创建方法根据传入的参数做if-else条件判断,决定最终创建什么样的产品对象。
•工厂方法模式由多个工厂类实现工厂接口,利用多态来创建不同的产品对象,从而避免了冗长的if-else条件判断。
•抽象工厂模式把产品子类进行分组,同组中的不同产品由同一个工厂子类的不同方法负责创建,从而减少了工厂子类的数量。
reference
程序员小灰:https://blog.csdn.net/bjweimengshu/article/details/108591085
https://blog.csdn.net/bjweimengshu/article/details/108459337