设计模式:工厂方法模式

导读

  • 工厂方法模式是所有设计模式中比较常用的一种模式,但是真正能搞懂用好的少之又少,Spring底层大量的使用该设计模式来进行封装,以致开发者阅读源代码被搞的晕头转向。

  • 今天陈某分别从以下五个方面详细讲述一下工厂方法模式:

  1. 「什么是工厂方法模式」

  2. 「通用框架实现」

  3. 「工厂方法模式的优点」

  4. 「工厂方法模式的升级」

  5. 「Spring底层如何使用工厂方法模式」

什么是工厂方法模式?

  • 定义:定义一个用于创建对象的 接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。

  • 工厂方法模式通用类图如下:

  • 在工厂方法模式中,抽象产品Product负责定义产品的特性,实现对事物的抽象定义。

  • AbstractFactory是抽象工厂类,定义了一个抽象工厂方法。具体如何创建产品由工厂实现类ConcreteFactory完成。

通用框架实现

  • 工厂方法模式的变种有很多,陈某给出一个比较实用的通用框架。

  • 抽象产品类

public abstract class Product {
    /**
     * 公共逻辑方法
     */
    public void method1(){}

    /**
     * 抽象方法:由子类实现,根据业务逻辑定义多个
     */
    public abstract void method2();
}
  • 具体产品类1,继承抽象产品类,如下:

public class Product1 extends Product {
    /**
     * 实现抽象产品类的抽象方法
     */
    @Override
    public void method2() {

    }
}
  • 具体产品类2,继承抽象产品类,如下:

public class Product2 extends Product {

    /**
     * 实现抽象产品类的抽象方法
     */
    @Override
    public void method2() {

    }
}
  • 抽象工厂类,必须定义一个工厂方法来让子类自己实现具体的创建逻辑,如下:

public abstract class AbstractFactory {
    /**
     * 工厂方法,需要子类实现
     * @param cls
     * @param <T>
     * @return
     */
    public abstract <T extends Product> T create(Class<T> cls);
}
  • 具体工厂类,使用了反射对具体产品的实例化,如下:

public class ConcreteFactory extends AbstractFactory {
    @Override
    public <T extends Product> T create(Class<T> cls) {
        Product product=null;
        try{
            product= (Product) Class.forName(cls.getName()).newInstance();
        }catch (Exception ex){
            ex.printStackTrace();
        }
        return (T) product;
    }
}
  • 测试如下:

public static void main(String[] args) {
        //创建具体工厂类
        ConcreteFactory factory = new ConcreteFactory();
        //调用工厂方法获取产品类1的实例
        Product1 product1 = factory.create(Product1.class);
        System.out.println(product1);
    }
  • 以上是简单的一个通用框架,读者可以根据自己的业务在其上拓展。

工厂方法模式的优点

  • 良好的封装性,代码结构清晰,调用者不用关心具体的实现过程,只需要提供对应的产品类名称即可。

  • 易扩展性,在增加产品类的情况下,只需要适当的修改工厂类逻辑或者重新拓展一个工厂类即可。

  • 屏蔽了产品类,产品类的变化调用者不用关心。比如在使用JDBC连接数据库时,只需要改动一个驱动的名称,数据库就会从Mysql切换到Oracle,极其灵活。

工厂方法模式的升级

  • 在复杂的系统中,一个产品的初始化过程是极其复杂的,仅仅一个具体工厂实现可能有些吃力,此时最好的做法就是为每个产品实现一个工厂,达到一个工厂类只负责生产一个产品。

  • 此时工厂方法模式的类图如下:

  • 如上图,每个产品类都对应了一个工厂,一个工厂只负责生产一个产品,非常符合单一职责原则。

  • 针对上述的升级过程,那么工厂方法中不需要传入抽象产品类了,因为一个工厂只负责一个产品的生产,此时的抽象工厂类如下:

public abstract class AbstractFactory {
    /**
     * 工厂方法,需要子类实现
     */
    public abstract <T extends Product> T create();
}

Spring底层如何使用工厂方法模式?

  • 工厂方法模式在Spring底层被广泛的使用,陈某今天举个最常用的例子就是AbstractFactoryBean

  • 这个抽象工厂很熟悉了,这里不再讨论具体的作用。其实现了FactoryBean接口,这个接口中getObject()方法返回真正的Bean实例。

  • AbstractFactoryBean中的getObject()方法如下:

public final T getObject() throws Exception {
    //单例,从缓存中取,或者暴露一个早期实例解决循环引用
  if (isSingleton()) {
   return (this.initialized ? this.singletonInstance : getEarlySingletonInstance());
  }
    //多实例
  else { 
      //调用createInstance
   return createInstance();
  }
 }
  //创建对象
  protected abstract T createInstance() throws Exception;
  • 从以上代码可以看出,创建对象的职责交给了createInstance这个抽象方法,由其子类去定制自己的创建逻辑。

  • 下图显示了继承了AbstractFactoryBean的具体工厂类,如下:

  • 其实与其说AbstractFactoryBean是抽象工厂类,不如说FactoryBean是真正的抽象工厂类,前者只是对后者的一种增强,完成大部分的可复用的逻辑。比如常用的sqlSessionFactoryBean只是简单的实现了FactoryBean,并未继承AbstractFactoryBean,至于结论如何,具体看你从哪方面看了。

总结

  • 工厂方法模式是一种常见的设计模式,但是真正能够用的高级,用的透彻还是有些难度的,开发者所能做的就是在此模式基础上思考如何优化自己的代码,达到易扩展、封装性强的效果了。

留言讨论区

往期推荐

SpringCloud 2020新版视频发布

小白进阶架构师就差这套2T视频资源了!!!

Spring解决循环依赖,你真的懂了吗?

老司机带你从源码开始撸Spring生命周期!!!

老司机带你聊聊接口限流!!! 幂等性如何实现?带你了解一波!!! Mysql性能优化:为什么要用覆盖索引? Mysql性能优化:什么是索引下推? Mysql性能优化:如何给字符串加索引? 设计模式:模板模式

设计模式:单例模式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不才陈某

欢迎关注公众号【码猿技术专栏】

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值