工厂设计模式
什么是简单工厂模式?
简单工厂模式是属于
创建型模式
,是工厂模式的一种。
简单工厂模式是由一个工厂对象决定创建出哪一种产品的实例
。简单工厂模式是工厂模式中最简单实用的模式。
简单工厂模式
:定义了一个创建对象的类,由这个类来封装实例化对象的行为。
使用场景
:在软件开发中,当我们会用到大量创建某种、某类或者某批对象时,(如:A用户发布动态/评论/回复等,B用户去点赞,这时就可以用上工厂模式)就会使用到工厂模式。
在Spring中的应用
实现方式
:
BeanFactory
。Spring中的BeanFactory就是简单工厂模式的具体表现,根据传入一个唯一的标识来获取Bean对象,但是是否在传入参数后创建还是在传入前创建这个要根据情况来定。
实质
:
由一个工厂类根据传入的参数,动态的决定应该创建哪一个产品类。
实现
:
bean容器的启动阶段
:
-
读取bean的xml配置文件,将bean元素分别转换成一个BeanDefinition对象。
-
然后通过BeanDefinitionRegistry将这些对象注册到beanFactory中,保存在一个ConcurrentHashMap中。
-
将BeanDefinition注册到beanFactory后,在这里Spring为我们提供了一个扩展的切口,允许我们通过实现接口BeanFactoryPostProcessor在此处来插入我们定义的代码。
典型的列子就是:PropertyPlaceholderConfigurer,我们一般在配置数据库的dataSource时使用到的占位符的值,就是它注入进去的。
容器中bean的实例化阶段
:
实例化阶段主要是通过反射或者CGLIB对bean进行实例化,在这个阶段Spring又给我们暴露了很多的扩展点:
-
各种的Aware接口
,比如:BeanFactoryAware,对于实现了Aware接口的bean,在实例化bean时Spring会帮我们注入对应的BeanFactory的实例。 -
BeanPostProcessor接口
,实现了它的接口的bean,在实例化bean时Spring会帮我们调用接口中的方法(重写了的方法postProcessBeforeInitialization()或postProcessAfterInitialization())。 -
InitializingBean接口
,实现了它的接口的bean,在实例化bean时Spring会帮我们调用接口中的方法(重写了的方法afterPropertiesSet())。 -
DisposableBean接口
,实现了这个接口的bean,在该bean死亡的时候Spring会帮我们调用接口中的方法(重写了的方法destroy())。
设计意义
:
松耦合。
可以将原来的硬编码的依赖,通过Spring这个beanFactory这个工厂来注入依赖,也就是说原来只有依赖方和被依赖方,现在我们引用了第三方–beanFactory,由它来解决bean之间的依赖问题,达到了松耦合的效果。
bean的额外处理。
通过spring的接口暴露,在实例化bean阶段我们可以进行一些额外的处理,这些额外的处理只需要让bean实现对应的接口即可,那么spring就会在bean的生命周期调用我们实现的接口来处理该bean。
工厂方法模式
-
工厂方法模式设计方案
:将披萨项目的实例化功能抽象成抽象方法,在不同的口味点餐子类中具体实现。 -
工厂方法模式
:定义了一个创建对象的抽象方法,由子类决定要实例化的类。
工厂方法模式将对象的实例化推迟到子类。
抽象工厂模式
-
抽象工厂模式
:定义了一个 interface 用于创建相关或有依赖关系的对象簇,而无需指明具体的类 - 抽象工厂模式可以将简单工厂模式和工厂方法模式进行整合。
- 从设计层面看,抽象工厂模式就是对简单工厂模式的改进(或者称为进一步的抽象)。
-
将工厂抽象成两层,AbsFactory(抽象工厂) 和 具体实现的工厂子类。
程序员可以根据创建对象类型使用对应 的工厂子类。这样将单个的简单工厂类变成了工厂簇,更利于代码的维护和扩展。
在Spring中的应用
实现方式
: FactoryBean接口。
实现原理
:实现了FactoryBean接口的bean是一类叫做factory的bean。其特点是,spring会在使用getBean()调用获得该bean时,会自动调用该bean的getObject()方法,所以返回的不是factory这个bean,而是bean.getObject()方法的返回值。
例⼦
:
例典型的例⼦有spring与mybatis的结合。
代码⽰例
:
<bean id="SqlSessionFactory" class="org.mybatis.spring.SqlSessionFactory">
<property name="driverClass" value="${jdbc.driver}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.uid}" />
<property name="password" value="${jdbc.pwd}" />
</bean>
说明
:
说我们看上⾯该bean,因为实现了FactoryBean接⼝,所以返回的不是 SqlSessionFactoryBean 的实例,⽽是它的 SqlSessionFactoryBean.getObject() 的返回值。