来源丨炭烧生蚝
juejin.im/post/5cc1a4755188252b4a5c30b0
索尔科姆港,英国 (© Devon and Cornwall Photography)
假设有一个司机, 需要到某个城市, 于是我们给他一辆汽车
如果我们希望给到这个司机的始终是一辆车, 应该怎么做? ( 单例 )
首先我们不能让司机自己通过 new产生一辆汽车, 而是应该通过调用 Car类中的某个方法对外提供车.
下面考虑, 如果我们不希望只有汽车这种交通工具, 我们希望可以定制交通工具, 并定制生产交通工具的流程, 应该怎么做?
一旦产生由汽车到交通工具这样的概念, 就应该想到多态. 我们可以定义一个 Moveable
接口, 在接口中声明 run()
方法, 所有的交通工具类都实现该接口.
对于定制生产流程, 我们可以通过一个工厂进行生产对应的交通工具.
下面把简单工厂的画面从脑海中清空, 讲述另一种工厂实现.
我们假设开头的司机不是一个普通的司机, 他除了需要一种交通工具以到达某个城市外, 他还需要一把AK47, 并且还需要一个苹果以备路上不时之需.
所以我们需要给他一个工厂来制造这一系列产品.
为了提高可扩展性, 我们还希望不同的工厂可以制作不同系列的产品, 比如上面说的A工厂制造的是汽车, AK47, 苹果; 而B工厂制造的是飞机, 火箭炮, 旺仔小馒头.
总结一下, 抽象工厂和简单工厂各有什么优劣?
抽象工厂能够生产一系列产品, 也能方便地替换掉一系列产品, 但是如果想要在产品系列中添加多一个品种将会非常麻烦. 比如说在上面的系列产品中添加一个盔甲抽象类, 那么抽象工厂以及对应的实现都要修改源码了.
而简单工厂能够灵活的生产但一个品种的产品, 但是如果生产的品种较多, 会出现工厂泛滥的问题.
两者优劣互补, 那么有没有可以兼容两者优点的工厂实现呢? 下面看 spring
的工厂实现, 它给出了一种解决方案.
我们再次考虑最原始的情况, 有一个 Moveable
接口, 里面有 run
方法, Car
小汽车类实现了该接口.
在 Spring
的 bean
工厂中, 新对象不是通过 new
关键字获取的, 而是通过配置文件获取的.
具体的过程是: 先读取配置文件获得该类的 class
对象, 然后通过 class
对象创建具体的实例对象.
上面是对 Spring
中 bean
工厂使用的模拟, 下面我们使用真实的 Spring
来生成 Car
对象, 对比一下.
经过对比我们发现我们自己写的简单工厂和 Spring
的 bean
工厂在使用上没有什么区别, 确实 Spring
使用起来就是这么简单, 下面我们模拟一下 Spring
的 bean
工厂实现.
模拟 IOC:
都说 Spring
是个 bean
容器, 以下的代码将展示它是如何生成 bean
, 并把 bean
放入容器中供用户获取的.
思路比较简单:
创建 BeanFactory
工厂接口, 添加方法 getBean()
.
创建 BeanFactory
的实现类 ClassPathXmlApplicationContext
. 将在该实现类中展示 IOC
的具体实现.
ClassPathXmlApplicationContext
需要一个 container
容器存放创建的 bean
对象, 这里使用 HashMap
实现.
在 ClassPathXmlApplicationContext
的构造方法中读取 spring
的配置文件, 这里使用到了 dom4j
. 读取配置文件后根据 bean
的 class
属性使用反射创建出 bean
对象. 然后把 id
和 bean
对象分别作为 key
和 value
添加到容器中.
当工厂被调用 getBean()
方法时, 从容器中找到对应的 bean
并返回.
后 记
若有错误或者不当之处,可在本公众号内反馈,一起学习交流!
更多热文在此:
● Spring Boot 系列实战文章合集(源码已开源)
● 程序员写简历时必须注意的技术词汇拼写
● 基于Spring Security OAuth2 的SSO单点登录+JWT权限控制实战
● 从一份配置清单详解Nginx服务器配置
● 如何在Windows下像Mac一样优雅的开发
● Docker容器可视化监控中心搭建
● 利用ELK搭建Docker容器化应用日志中心
● RPC框架实践之:Google gRPC
● 一文详解 Linux系统常用监控工具
更多 务实、能看懂、可复现的 技术文章尽在公众号 CodeSheep ,欢迎扫码订阅,第一时间获取更新 :arrow_down::arrow_down::arrow_down: