Spring中的设计模式:工厂方法模式
导读
- 工厂方法模式是所有设计模式中比较常用的一种模式,但是真正能搞懂用好的少之又少,Spring底层大量的使用该设计模式来进行封装,以致开发者阅读源代码的时候晕头转向。
- 文章首发于微信公众号【码猿技术专栏】,原创不易,谢谢支持!!!
- 今天陈某分别从以下五个方面详细讲述一下工厂方法模式:
- 「从什么是工厂方法模式」
- 「通用框架实现」
- 「工厂方法模式的优点」
- 「工厂方法模式的升级」
- 「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,至于结论如何,具体看你从哪方面看了。
总结
- 工厂方法模式是一种常见的设计模式,但是真正能够用的高级,用的透彻还是有些难度的,开发者所能做的就是在此模式基础上思考如何优化自己的代码,达到易扩展、封装性强的效果了。
Spring中的设计模式:工厂方法模式的更多相关文章
- 深入浅出设计模式——工厂方法模式(Factory Method)
介绍在简单工厂模式中,我们提到,工厂方法模式是简单工厂模式的一个延伸,它属于Gof23中设计模式的创建型设计模式.它解决的仍然是软件设计中与创建对象有关的问题.它可以更好的处理客户的需求变化. 引入我 ...
- 4. 星际争霸之php设计模式--工厂方法模式
题记==============================================================================本php设计模式专辑来源于博客(jymo ...
- C++设计模式——工厂方法模式
本文版权归果冻说所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利.» 本文链接:http://www.jellythink.com/arch ...
- 设计模式——工厂方法模式(Factory Method)
原文地址:http://www.cnblogs.com/Bobby0322/p/4179921.html 介绍 在简单工厂模式中,我们提到,工厂方法模式是简单工厂模式的一个延伸,它属于Gof23中设计 ...
- Java设计模式-工厂方法模式(Virtual Constructor/Polymorphic Factory)
工厂方法模式(Virtual Constructor/Polymorphic Factory) 工厂方法模式是类的创建模式,又叫做虚拟构造子模式(Virtual Constructor)或者多态性工厂 ...
- 设计模式--工厂方法模式(Factory method pattern)及应用
面向对象的好处: 通过封装,继承,多态把程序的耦合度降低. 用设计模式可以使程序更加灵活,容易修改,且易于复用. 1. 工厂方法模式 Define an interface for creating ...
- JAVA设计模式--工厂方法模式
工厂方法设计模式 抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关.是具体工厂角色必须实现的接口或者必须继承的父类.在java中它由抽象类或者接口来实现.具体工厂角色:它含有和具体业务逻辑有关 ...
- 我的Java设计模式-工厂方法模式
女朋友dodo闹脾气,气势汹汹的说"我要吃雪糕".笔者心里啊乐滋滋的,一支雪糕就能哄回来,不亦乐乎?! 但是,雪糕买回来了,她竟然说"不想吃雪糕了,突然想吃披萨" ...
- 设计模式 — 工厂方法模式(Factory Method)
在开发系统中,经常会碰到一个问题.现在需要实现的一些功能,但是这个功能模块以后一定是需要扩展的,那么现在开发中就不仅要实现现在的功能,还要考虑以后的扩展.那么为了系统的健壮,扩展就要遵循开闭原则(简单 ...
- C#设计模式--工厂方法模式
0.C#设计模式-简单工厂模式 设计模式: 工厂方法模式(Factory Method Pattern) 介绍:简单工厂模式是要在工厂类中通过数据来做个决策,在工厂类中的多个类中实例化出来其中一个要用 ...
随机推荐
- fsLayuiPlugin配置说明
fsLayuiPlugin 是一个基于layui的快速开发插件,支持数据表格增删改查操作,提供通用的组件,通过配置html实现数据请求,减少前端js重复开发的工作. GitHub下载 码云下载 测试环 ...
- JavaScript两道例题
1.有一个卡车司机肇事后想逃跑,但是被三个人看见其车牌号码,但是没有看全.一号说:车牌的前两位是一样的,二号说:车牌的后两位是一 样的,但是与前两位不一样,三号说:车牌是一个数字的平方,请计算车辆号牌 ...
- Java 读取Word中的脚注、尾注
本文介绍读取Word中的脚注及尾注的方法,添加脚注.尾注可以参考这篇文章. 注:本文使用了Word类库(Free Spire.Doc for Java 免费版)来读取,获取该类库可通过官网下载,并解压 ...
- Thead基础及两种创建方式
今天本人给大家讲解一下多线程,如有不对的或者讲的不好的可以多多提出,我会进行相应的更改,先提前感谢提出意见的各位了!!! 说说多线程本人自己对它理解的定义:因计算机的CPU支持能够在同一时间执行多于一 ...
- JetBrains全系列产品2019.3.2注解教程
1.JetBrains官方网站 https://www.jetbrains.com/ JetBrains是一家捷克的软件开发公司 IDE工具: * IntelliJ IDEA 一套智慧型的Jav ...
- Keil MDK版兼容51系列单片机开发环境安装
一.安装源文件下载 百度网盘链接:https://pan.baidu.com/s/18tnjFgVat4q2hDSh7LAD8A 提取码: 2295 二.安装及破解 1.安装51的编辑器 双击安 ...
- 上线前测试的bug,要不要处理,跟版本的关系
最近有两个项目是在旧版本上实施的.上线前经过一轮测试后,发现了一些产品(我们的产品确实不稳定) 在这个项目上,修改产品bug是肯定的.但是要不要追踪这些bug? 这就跟版本使用范围有关系了,毕竟要考虑 ...
- BeetleX.FastHttpApi之测试插件集成
说到Webapi测试工具相信很多人想起Swagger,它可以非常方便地集成到项目中并进行项目Webapi接口测试.而BeetleX.FastHttpApi在新版本中也提供类似的插件,只需要引用这个插件 ...
- Go 武林外传 - 初出茅庐
没有旁白. 我叫小白, 白痴的白. 老头说我太笨了, 提前放我下山, 让我自生自灭. 对了, 忘了说了, 那老头是我师傅. 虽然我的内心深处是拒绝的, 但是我又打不过老头, 只好收拾铺盖滚犊子了. 算 ...
- 【Weiss】【第03章】练习3.13:桶排序
[练习3.13] 利用社会安全号码对学生记录构成的数组排序.编写一个程序进行这件工作,使用具有1000个桶的基数排序并且分三趟进行. Answer: 首先,对社会安全号码不了解的就把它当成一个不超过9 ...