简单工厂模式
简单工厂模式是指:使用一个单独的类去实现创造实例的过程,该类就被称为工厂类
举个栗子
假设这里要实现一个计算器,为了将计算器的功能进行隔离(对加减乘除的方法进行隔离,使其互不干扰,又为了提取公共的运算部分),将公共部分放在一个超类,然后对应去实现不同运算功能的子类
一个功能就对应一个类

简单工厂类根据页面传来的类型来调用不同模块

也就是将实例对象的能力交给了简单工厂类去进行
这个模式遵循了单一职责,却违反了开放封闭原则,一旦我要添加新的计算功能,就要去修改工厂里面的switch分支,修改了原有的类。
工厂模式
简单工厂模式违反了开放封闭原则,所以就有了工厂模式
工厂模式是指:定义一个用于创建对象的接口,让子类去决定实例化哪一个类,让一个类的实例延迟到其子类去进行
关键就在于,逻辑判断的代码放在了简单工厂类里面,这是简单工厂模式的优点,也是其缺点
- 优点在于工厂类里面包含了必要的逻辑判断,根据客户端的选择条件去动态实例化相关的类,对于客户端来说,去除了客户端对具体产品的依赖性
- 缺点也在于工厂类里面包含了必要的逻辑判断,一旦需要增加新的实例化类时,工厂类自己也要需要去进行修改,违反了开放封闭原则
缺点的问题就出现在工厂并不是面向抽象的,而是面向实际,解决的思路就是将工厂也抽象起来,不同的实例要由不同的工厂去进行创建
将工厂抽象起来,这里共有4个工厂

对应的产品如下

那么页面交互的地方要调用的代码如下(页面掌控了具体调用工厂的逻辑)

那么此时,如果我们要新增产品(Product)时,要去添加两个新类(一个实现Product,另一个实现IFactory),一个是新产品,另外一个是新工厂,那么就符合了开放封闭原则,对原有工厂类的修改封闭,对工厂类的拓展新类进行开放
简单来说,工厂把简单工厂的内部逻辑判断转移到了客户端上,本来新增产品是要修改工厂类的,现在是修改客户端上面
抽象工厂模式
抽象工厂模式是指:提供一个创建一系列相关或相互依赖对象的接口,而无需去指定它们具体的类
其实抽象工厂模式跟工厂模式类似,只不过工厂模式是针对一种抽象产品有不同实例的,所以工厂接口里面只能生成一个抽象产品,而抽象工厂模式是针对多种抽象产品,而抽象的工厂接口里面包含所有的抽象产品的建造方法,也就是该工厂不局限于只有一个抽象产品了,该工厂有一系列产品
比如这里有两个抽象产品


那么对应的抽象工厂应该有这两个产品的抽象生产方法
/**
* @Author: Ember
* @Date: 2021/6/1 22:03
* @Description:
*/
public interface IFactory {
public ProductA createA();
public ProductB createB();
}
class AccessFactory implements IFactory{
@Override
public ProductA createA() {
return new ProductAOne();
}
@Override
public ProductB createB() {
return new ProductBOne();
}
}
class SQLFactory implements IFactory{
@Override
public ProductA createA() {
return new ProductATwo();
}
@Override
public ProductB createB() {
return new ProductBTwo();
}
}
而客户端的调用依然是只要去修改对应实例的工厂即可,与工厂模式的客户端修改几乎一样

抽象工厂模式的优点与缺点
-
便于交换产品系列,只要去改动客户端使用的抽象工厂实例即可,那么就可以获取同种抽象,但不同系列的产品
-
让具体的产品创建实例与客户端分离,客户端仅仅是通过工厂的抽象接口来创建实例的,对产品是不可见的(连产品实例的名字也不知道)。
-
缺点在于,每当新增一个新的抽象产品时,要增加的其他类也加多了,比如该新抽象产品的对应各个工厂的具体实例,同时要修改的地方也加多了,各个工厂都要增加对于该抽象产品的实现创建方法(因为抽象工厂增加了该抽象产品的创建方法)
-
客户端对产品虽然仍然不可视,但破坏了封闭开放原则
所以设计的时候,就一定要提前想好抽象产品,不要随意进行新增。
简单工厂优化抽象工厂
抽象工厂之所以新增产品如此困难,原因就在于工厂太多了,所以可以将所有的工厂合并成一个简单工厂,那么只需要去修改一个简单工厂类即可。
public class ConcreateFactory implements IFactory{
private static final String TYPE = "SQL";
//private static final String TYPE = "ACCESS";
@Override
public ProductA createA() {
switch (TYPE){
case "SQL":{
return new ProductAOne();
}
case "ACCESS":{
return new ProductATwo();
}
}
return null;
}
@Override
public ProductB createB() {
switch (TYPE){
case "SQL":{
return new ProductBOne();
}
case "ACCESS":{
return new ProductBTwo();
}
}
return null;
}
}
这里使用简单工厂模式还将工厂名字(TYPE)给封装起来,那么客户端那边对工厂名字甚至不可见,所以客户端什么都不用改,所有的修改都在简单工厂里面进行修改就可以了。
但缺点仍然存在,存在大量的switch,破坏了开放封闭原则
反射+抽象工厂
通过反射,我们就可以根据类名动态去创建产品,减少一大堆的switch去进行切换,当然这里实现的前提是,产品的类名与工厂名字有所关联
举个栗子
这是抽象产品及其对应的实例

那么我们的简单工厂就变成这样,通过反射去获取对应的实际产品
/**
* @Author: Ember
* @Date: 2021/6/1 22:43
* @Description:
*/
public class DataAccessFactory implements IFactory{
private static final String TYPE = "SQL";
//这里也是可以改动,然后对应生产同一下列不同实际的产品
//private static final String TYPE = "Access";
@Override
public ProductOne getOne() {
try {
Class<?> aClass = Class.forName(TYPE + "Product");
Object o = aClass.newInstance();
return (ProductOne) o;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
return null;
}
@Override
public ProductTwo getTwo() {
try {
Class<?> aClass = Class.forName(TYPE + "ProductTwo");
Object o = aClass.newInstance();
return (ProductTwo) o;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
return null;
}
}
没有了大量的switch,那么我们就可以不需要改动原有产品的生产代码,添加新产品的时候,只需要添加对应反射生产实际新产品的代码即可。
这里还能做一个优化就是,我们可以利用配置文件来去修改工厂里面的TYPE配置,那么就不必改动源代码文件了。
所有在用简单工厂的地方,考虑使用反射技术来去除switch或if,解除由于大量的switch带来的耦合
三种模式的区别,与使用场景
-
工厂模式克服了简单工厂违背开放-封闭原则的缺点,而且保持了封装对象创建过程的优点(封装了产品的创建)
-
工厂模式与简单工厂模式都实现了客户端与产品对象的解耦合(抽象工厂模式的客户端修改的是工厂类,创建产品的细节依然在工厂类里面,所以仍然是与产品对象解耦合)
-
工厂模式是简单工厂模式的进一步抽象和推广,但缺点在于,工厂模式会导致更多的类生成,因为不仅要新系列产品还要新工厂
-
在业务中,抽象产品的系列越来越多,一个抽象工厂也不再只是单独生产一个系列的抽象产品,那么工厂模式就变成了抽象工厂模式
-
抽象工厂模式保留了工厂模式的优点,就是对于同一系列的衍生产品符合开放封闭原则的
-
但是当要新增抽象产品的时候,就要去进行改动很多类,抽象工厂类、实际工厂类、抽象产品类,都要去进行新增或改动,不符合开放封闭原则
-
使用简单工厂模式来优化抽象工厂模式,通过将工厂合并起来,可以减少改动的抽象工厂类,只需要改动简单工厂即可
-
再利用反射和配置文件,可以减少简单工厂里面大量的switch或if分支带来的耦合,让已有的产品创建方法不需要进行改动
本文详细介绍了简单工厂模式、工厂模式和抽象工厂模式。简单工厂模式将实例创建交给工厂类,但违反开放封闭原则;工厂模式将工厂抽象,解决了部分问题;抽象工厂模式针对多种抽象产品。还分析了抽象工厂模式优缺点,介绍了简单工厂优化及反射结合的方法,并对比了三种模式的区别与使用场景。
1478

被折叠的 条评论
为什么被折叠?



