Spring设计模式探幽(1)

2019-04-13 20:46发布

设计伊始

Spring 是为解决企业级应用开发的复杂性而设计,她可以做很多事。但归根到底支撑Spring的仅仅是少许的基本理念,而所有地这些的基本理念都能可以追溯到一个最根本的使命:简化开发。这是一个郑重的承诺,其实许多框架都声称在某些方面做了简化。 而Spring则立志于全方面的简化Java开发。对此,她主要采取了4个关键策略: 1,基于POJO的轻量级和最小侵入性编程; 2,通过依赖注入和面向接口松耦合; 3,基于切面和惯性进行声明式编程; 4,通过切面和模板减少样板式代码; 而他主要是通过:面向Bean、依赖注入以及面向切面这三种方式来达成的。 而设计如此精妙的spring,其中肯定是有许多设计模式的,下面我们就通过阅读分析spring的源码来感受spring的密码。 贴一个spring源码下载地址,下载托管在github了。 https://github.com/spring-projects/spring-framework/tags 我下的是spring3.2.5 release

常见的九种设计模式

分别是:简单工厂、工厂方法、单例模式、适配器模式、包装器模式、代理模式、观察者模式、策略模式、模板方法模式

1.工厂模式

org.springframework.beans.factory 这里是定义spring IOC容器接口的包,在这个包里有我们熟悉的BeanFactory package org.springframework.beans.factory; public interface BeanFactory { /** *这里是对FactoryBean的转义定义,如果使用bean的名字检索FactoryBean,得到的是工厂生成的对象, *如果需要得到工厂本身,需要转义。For example, if the bean named * myJndiObject is a FactoryBean, getting &myJndiObject * will return the factory */ String FACTORY_BEAN_PREFIX = "&"; /** *这里根据bean的名字,在IOC容器中得到bean实例,这个IOC容器就是一个大的抽象工厂。 */ Object getBean(String name) throws BeansException; /** *这里根据bean的名字和Class类型来得到bean实例,和上面的方法不同在于它会抛出异常:如果 *根据名字取得的bean实例的Class类型和需要的不同的话。 */ Object getBean(String name, Class requiredType) throws BeansException; /** *这里提供对bean的检索,看看是否在IOC容器有这个名字的bean */ boolean containsBean(String name); /** *这里根据bean名字得到bean实例,并同时判断这个bean是不是单例 */ boolean isSingleton(String name) throws NoSuchBeanDefinitionException; /** *这里得到bean实例的Class类型 */ Class getType(String name) throws NoSuchBeanDefinitionException; /** *这里得到bean的别名,如果根据别名检索,那么其原名也会被检索出来 */ String[] getAliases(String name); }
  1. spring中BeanFactory和ApplicationContext的创建中都用到了典型的静态工厂模式。Bean 的创建采用了的工厂模式,他的顶级接口是 BeanFactory。BeanFactory 有三个子接口:ListableBeanFactory、HierarchicalBeanFactory 和 AutowireCapableBeanFactor。这三个接口主要是为了区分在 Spring 内部在操作过程中对象的传递和转化过程中,对对象的数据访问所做的限制。这三个子接口集成了顶级接口并对BeanFactory的功能进行了增强,称为二级接口;ConfigurableBeanFactory对二级接口HierarchicalBeanFactory进行了再次增强,它还继承了另一个外来的接口SingletonBeanRegistry,可以被称为三级接口;ConfigurableListableBeanFactory是一个更强大的接口,继承了上述的所有接口,称为四级接口。其余的为抽象类,实现了Spring Bean四级接口所定义的所有功能。
    spring
一般来说采用BeanFactory的子接口ApplicationContext来创建BeanFactory的实例。ApplicationContext通常使用如下两个实现类:
FileSystemXmlApplicationContext:以基于文件系统的XML配置文件创建ApplicationContext实例。
ClassPathXmlApplicationContext:以类加载路径下的XML配置文件创建的ApplicationContext实例 public void testAC() { //1.在这里ApplicationContext接口继承了ListableBeanFactory, HierarchicalBeanFactory等二级接口 ApplicationContext ac = new ClassPathXmlApplicationContext("cn/xyf/a_hello/applicationContext.xml"); //2.从容器获取Bean User user = (User) ac.getBean("user"); System.out.println(user); }
  • 在spring中,BeanFactory拥有类似的功能,它负责实例化、配置和管理对象。我们一般用的BeanFactory的实现类ApplicationContext,这个类会自动解析我们配置的applicationContext.xml,然后调用实现后的getBean方法然后根据我们配置的bean来new对象,将new好的对象放进一个容器中,键就是我们bean的id,值就是new的对象。
  • 在这里给出简单工厂模式的实现
//简单工厂模式 package cn.xyf.factory; /** * @author Dale * 封装一个雷峰类 */ public class LeiFeng { //扫地 public void sweep(){ System.out.println("扫地"); } //洗衣 public void wash(){ System.out.println("洗衣"); } //买米 public void buyRice(){ System.out.println("买米"); } } //大学生子类 class UnderGraduate extends LeiFeng{ } //社区志愿者子类 class Volunteer extends LeiFeng{ } package cn.xyf.factory; /** * @author Dale * 简单工厂模式 */ public class SimpleFactory { //静态方法创建雷锋对象 public static LeiFeng createLeiFeng(String type){ LeiFeng result = null; switch(type){ case "UnderGraduate": result = new UnderGraduate(); break; case "UnderGrate": result = new Volunteer(); break; } return result; } } package cn.xyf.factory; /** * @author Dale * java 工厂模式 */ public class Client { public static void main(String[] args) { //1.简单工厂模式 LeiFeng s1 = SimpleFactory.createLeiFeng("UnderGraduate"); LeiFeng s2 = SimpleFactory.createLeiFeng("UnderGrate"); s1.wash(); s2.buyRice(); }
  • 在这里补充一下简单工厂、工厂、抽象工厂三者的区别
    1. 简单工厂
      简单工厂模式的工厂类一般是使用静态方法,通过接收的参数的不同来返回不同的对象实例。
      不修改代码的话,是无法扩展的。
    2. 工厂方法
      工厂方法是针对每一种产品提供一个工厂类。通过不同的工厂实例来创建不同的产品实例。
      在同一等级结构中,支持增加任意产品。
    3. 抽象工厂
      抽象工厂是应对产品族概念的。比如说,每个汽车公司可能要同时生产轿车,货车,客车,那么每一个工厂都要有创建轿车,货车和客车的方法。
      应对产品族概念而生,增加新的产品线很容易,但是无法增加新的产品。
  • 小结
★工厂模式中,重要的是工厂类,而不是产品类。产品类可以是多种形式,多层继承或者是单个类都是可以的。但要明确的,工厂模式的接口只会返回一种类型的实例,这是在设计产品类的时候需要注意的,最好是有父类或者共同实现的接口。 ★使用工厂模式,返回的实例一定是工厂创建的,而不是从其他对象中获取的。 ★工厂模式返回的实例可以不是新创建的,返回由工厂创建好的实例也是可以的。 区别 简单工厂 : 用来生产同一等级结构中的任意产品。(对于增加新的产品,无能为力) 工厂方法 :用来生产同一等级结构中的固定产品。(支持增加任意产品)
抽象工厂 :用来生产不同产品族的全部产品。(对于增加新的产品,无能为力;支持增加产品族) 以上三种工厂 方法在等级结构和产品族这两个方向上的支持程度不同。所以要根据情况考虑应该使用哪种方法。