三大类设计模式
- 创建型模式(5种):工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式
- 结构型模式(7种):适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模式,享元模式
- 行为型模式(11种):策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式
设计模式遵循的原则
- 开闭原则
- 里氏替换原则
- 依赖倒置原则
- 接口隔离原则
- 迪米特法则
- 单一职责原则
Spring 中的设计模式
简单工厂
又叫做静态工厂方法(StaticFactory Method)模式,但不属于23种GOF设计模式之一。
简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类。
Spring 中的 BeanFactory 就是简单工厂模式的体现,根据传入一个唯一的标识来获得 bean 对象,但是否是在传入参数后创建还是传入参数前创建这个要根据具体情况来定。
如下配置
<beans>
<bean id="bmwCar" class="cn.ltysyn.factoryMethod.CarStaticFactory" factory-method="getCar">
<constructor-arg value="1">bmwCar</constructor-arg>
</bean>
<bean id="audiCar" class="cn.ltysyn.factoryMethod.CarStaticFactory" factory-method="getCar">
<constructor-arg value="2">audiCar</constructor-arg>
</bean>
</beans>
工厂方法(Factory Method)
定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类。
Spring 中的 FactoryBean 就是典型的工厂方法模式
spring 中 BeanFactory 和 FactoryBean 的区别
区别:BeanFactory 是个 Factory,也就是 IOC 容器或对象工厂,FactoryBean 是个 Bean。在 Spring 中,所有的 Bean 都是由 BeanFactory (也就是 IOC 容器)来进行管理的。但对 FactoryBean 而言,这个 Bean 不是简单的 Bean,而是一个能生产或者修饰对象生成的工厂 Bean,它的实现与设计模式中的工厂模式和修饰器模式类似
factoryBean 相当于 beanfactory.getbean,这个返回的 bean 就是 factorybean 中 getObject 中返回的对象
关于获取
如果一个 bean 叫做 testObject,那么 getBean(“testObject”) 将获取该 bean,如果 getBean(“&testObject”) 将获取 FactoryBean
// bean
@Test
public void test2() throws Exception{
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("factory-bean.xml");
DBOperation dBoperation = applicationContext.getBean("proxyDB",DBOperation.class);
MysqlDBEntity dbEntity = new MysqlDBEntity();
dBoperation.save(dbEntity);
}
// factoryBean
@Test
public void test2() throws Exception{
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("factory-bean.xml");
FactoryBean factoryBean = applicationContext.getBean("&proxyDB",FactoryBean.class);
DBOperation db = (DBOperation)factoryBean.getObject();
MysqlDBEntity dbEntity = new MysqlDBEntity();
db.save(dbEntity);
}
- BeanFactory
BeanFactory,以 Factory 结尾,表示它是一个工厂类(接口),它负责生产和管理 bean 的一个工厂。在 Spring 中,BeanFactory 是 IOC 容器的核心接口,它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。BeanFactory 只是个接口,并不是 IOC 容器的具体实现,但是 Spring 容器给出了很多种实现,如 DefaultListableBeanFactory、XmlBeanFactory、ApplicationContext 等,其中 XmlBeanFactory 就是常用的一个,该实现将以 XML 方式描述组成应用的对象及对象间的依赖关系。XmlBeanFactory 类将持有此 XML 配置元数据,并用它来构建一个完全可配置的系统或应用。
BeanFactory 和 ApplicationContext 就是 Spring 框架的两个 IOC 容器,现在一般使用 ApplicationnContext,其不但包含了 BeanFactory 的作用,同时还进行更多的扩展。
Resource resource = new FileSystemResource("beans.xml");
BeanFactory factory = new XmlBeanFactory(resource);
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] { "applicationContext.xml", "applicationContext-part2.xml" });
BeanFactory factory = (BeanFactory) context;
// 接着使用 getBean(String beanName) 方法就可以取得 bean 的实例;
- FactoryBean
一般情况下,Spring 通过反射机制利用
<bean>
的 class 属性指定实现类实例化 Bean,在某些情况下,实例化 Bean 过程比较复杂,如果按照传统的方式,则需要在<bean>
中提供大量的配置信息。配置方式的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。Spring 为此提供了一个 org.springframework.bean.factory.FactoryBean 的工厂类接口,用户可以通过实现该接口定制实例化 Bean 的逻辑。FactoryBean 接口对于 Spring 框架来说占用重要的地位, Spring 自身就提供了 70 多个 FactoryBean 的实现。它们隐藏了实例化一些复杂 Bean 的细节,给上层应用带来了便利。从 Spring3.0 开始,FactoryBean 开始支持泛型,即接口声明改为 FactoryBean 的形式
以 Bean 结尾,表示它是一个 Bean,不同于普通 Bean 的是:它是实现了 FactoryBean 接口的 Bean,根据该 Bean 的 ID 从 BeanFactory 中获取的实际上是FactoryBean 的 getObject() 返回的对象,而不是 FactoryBean 本身,如果要获取 FactoryBean 对象,请在 id 前面加一个&符号来获取。
- 综上
- 两者都是接口
- 实现 BeanFactory 接口的类表明此类事一个工厂,作用就是配置、新建、管理各种 Bean
- 而实现 FactoryBean 的类表明此类也是一个 Bean,类型为工厂 Bean( Spring 中共有两种 bean,一种为普通 bean,另一种则为工厂 bean)。顾名思义,它也是用来管理 Bean的,而它本身由 Spring 管理。
一个 Bean 想要实现 FactoryBean
,必须实现以下三个接口
Object getObject():返回由FactoryBean创建的Bean的实例
boolean isSingleton():确定由FactoryBean创建的Bean的作用域是singleton还是prototype;
getObjectType():返回FactoryBean创建的Bean的类型。
有一点需要注意,如果将一个实现了 FactoryBean 的类成功配置到了 Spring 上下文中,那么通过该类对象的名称(比如 appleFactoryBean )从 Spring 的 applicationContext 或者 beanFactory 获取 bean 时,获取到的是 appleFactoryBean 创建的 apple 实例,而不是 appleFactoryBean 自己,如果想通过 Spring 拿到 appleFactoryBean,需要在名称前加 & 符号
单例模式(Singleton)
- 保证一个类仅有一个实例,并提供一个访问它的全局访问点。
spring中的单例模式完成了后半句话,即提供了全局的访问点BeanFactory。但没有从构造器级别去控制单例,这是因为spring管理的是是任意的java对象。
核心提示点:Spring 下默认的 bean 均为 singleton,可以通过singleton="true|false"
或者scope="?"
来指定
所有的单例模式都是使用静态方法进行创建的,所以单例对象在内存中静态共享区中存储。
懒汉式和饿汉式
- 懒汉式单例模式:在类加载时不初始化。
- 饿汉式单例模式:在类加载时就完成了初始化,所以类加载比较慢,但获取对象的速度快。
懒汉式单例模式
// 懒汉,线程不安全
public class SingletonDemo1 {
private static SingletonDemo1 instance;
private SingletonDemo1() {}
public static SingletonDemo1 getInstance() {
if (instance == null) {
instance = new SingletonDemo1();
}
return instance;
}
}
// 线程安全
public class SingletonDemo2 {
private static SingletonDemo2 instance;
private SingletonDemo2() {}
public static synchronized SingletonDemo2 getInstance() {
if (instance == null) {
instance = new SingletonDemo2();
}
return instance;
}
}
饿汉式单例模式
/**
* 基于classloder机制避免了多线程的同步问题
* instance 在类装载时就实例化,这时候初始化 instance 显然没有达到 lazy loading 的效果
*/
public class SingletonDemo3 {
private static SingletonDemo3 instance = new SingletonDemo3();
private SingletonDemo3() {}
public static SingletonDemo3 getInstance() {
return instance;
}
}