设计模式在Spring中的应用
设计模式的分类
总体来说设计模式分为三大类:
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
当然也有较小众的:
接口型模式,共四种:适配器模式、外观模式、组合模式、桥接模式。
职责型模式,共六种:单例模式、观察者模式、中介者模式、代理模式、责任链模式、享元模式。
构造型模式,共五种:建造者模式、工厂方法模式、抽象工厂模式、原型模式、备忘录模式。
操作性模式,共五种:模板方法模式、状态模式、策略模式、命令模式、解释器模式。
扩展型模式,共三种:装饰器模式、迭代子模式、访问者模式。
现根据较为大众的GOF分类方法说明在spring中的应用
1.工厂方法模式
2.抽象工厂模式
3.单例模式
Spring 中 bean 的默认作用域就是 singleton(单例)的,spring中单例可谓是随处可见了。
4.建造者模式
BeanDefinitionBuilder,UriComponentsBuilder等以Builder命名的类,基本都使用了该模式。
5.原型模式
scope=“prototype” 代表的是 多例 通常使用prototype,即每个bean 都是一个新实例。
6.适配器模式
有三种分类:
类适配器 (通过继承适配者进行实现)
对象适配器(通过引用适配者进行组合实现)
接口适配器 (通过抽象类来实现适配,中间写一个抽象类来减少当前类所需实现的接口方法)
servlet 分发时的 HandlerAdapter,以及 AOP 中拦截时使用的AdvisorAdapter。spring 中以Adapter结尾的类通常都是适配器
7.装饰器模式
与适配器模式不同点主要体现在 模式目的不同适配器模式主要是将A变成B而装饰器模式 是将A变成A+。
读取xml配置()时 创建bean 后,属性的增加就是使用了装饰模式DefaultBeanDefinitionDocumentReader.processBeanDefinition
TransactionAwareCacheDecorator的缓存事务中也较明显的体现了。
另外还有不少文章说到 dataSource 但是本人未找到相关代码体现。
8.代理模式
9.外观模式
主要是对复杂的逻辑进行封装暴露一个简单接口(方法)供外部使用,比如JdbcUtils。
10.桥接模式
桥接是指将2个东西连通重点在分开2个东西,而适配器是把2个当成1个用意在合。日志就是一个典型的桥接
11.组合模式
12.享元模式
单例模式是类级别的,一个类只能有一个对象实例;
享元模式是对象级别的,可以有多个对象实例,多个变量引用同一个对象实例
13.策略模式
所谓策略就是一种方案,策略模式即是实现同一目的的不同方案(不用管每个具体方案如何实现,可能不同策略中使用了组合模式,适配器模式等)。工厂模式:侧重对象的建立,而策略模式侧重方法的实现。可以说一个是一个是将生成对象进行了封装,一个是对目的 的多个实现方案进行封装。
DispatcherServlet.initStrategies()方法就初始化了各种bean,给个方法的bean列表就是各种策略。在web请求是根据不同场合使用不同的策略。
Spring中代理对象的创建使用了策略模式。抽象策略是AopProxy接口,Cglib2AopProxy和JdkDynamicAopProxy分别代表两种策略的实现方式,ProxyFactoryBean就是代表Context角色,它根据条件选择使用Jdk代理方式还是CGLIB方式。
可参考 https://www.cnblogs.com/zcmzex/p/8822509.html
说明了具体判断的流程。
此外 Spring 框架的资源访问接口也是基于策略设计模式实现的。
14.模板方法模式
在父类中定义流程 并对于某个核心方法或差异方法由子类各自实现。
例如AbstractApplicationContext最重要的refresh方法使用模板方法模式实现。
Spring 的ApplicationContext的最重要的几个实现类型:ClassPathXmlApplicationContext、AnnotationConfigApplicationContext、AnnotationConfigWebApplicationContext等,初始化都调用父类AbstractApplicationContext的refresh()模板方法。
此外Spring中 SpringJDBC使用模板方法模式实现。
可参考 https://www.cnblogs.com/linlf03/p/11221498.html
https://www.cnblogs.com/linlf03/p/11221498.html
15.观察者模式
spring中监听器 就是一个典型的观察者模式
https://www.iteye.com/blog/abc08010051-1972960
16.迭代子模式
CompositeIterator 扩展迭代器模式。(暂未涉及候补)
https://blog.csdn.net/codejas/article/details/79186349
17.责任链模式
1.filter的使用
2.dispatcherServlet 中
此处获取HandlerExecutionChain 以及其属性interceptors 都可以认为是一个责任链。
3.springAOP 中也使用该责任链模式
DynamicAdvisedInterceptor中
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
则是一个链式责任链
https://www.cnblogs.com/dengrong/p/10809922.html
18.命令模式
行为发起者与行为执行者解耦
spring中的jdbc模板中就使用了该模式
真正执行方法 的是
有时候看起来像是2个适配器模式 ,(一个针对类上的,一个针对方法上的)暂时无法总结这2个模式区别,望熟悉的大佬指教一二。
19.备忘录模式
撤销
spring中未见过以及相关文章,有了解者烦请留言告知。
20.状态模式
状态模式是策略模式的孪生兄弟,是因为它们的UML图是一样的。
但意图却完全不一样,策略模式是让用户指定更换的策略算法,而状态模式是状态在满足一定条件下的自动更换,用户无法指定状态,最多只能设置初始状态
在spring中的应用暂时未涉及 相关文章没有找到后续补充
21.访问者模式
Scopifier scopifier中已经定义,对于不同的StringValueResolver访问者 进行不同的操作。
访问者模式优点: 扩展性好,可以在不修改对象结构中的元素的情况下,为对象结构中的元素添加新的功能;
符合单一职责原则,通过访问者将无关的行为分离,使职责单一;访问者模式缺点: 违反了迪米特原则,因为具体元素对访问者公布细节; 违反了依赖倒置原则,依赖了具体类,没有依赖抽象;
对象结构变化困难,若对象结构发生了改变,访问者的接口和访问者的实现也都要发生相应的改变;使用场景: 对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作;
需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,也不希望在增加新操作时修改这些类。
22.中介者模式
spring 暂未找到相关代码和文章 待补充
中介者模式优点: 灵活性高,因为将同事类进行了解耦,使其不必有关联性;降低了类的复杂度,将一对多转化成了一对一;
中介者模式缺点: 中介者使用过多,会使系统变得复杂难以维护; 使用场景: 通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。
** 注意事项**:若不明确各个类的职责,那么就不要进行使用!
和外观模式、代理模式比较 中介者模式和外观模式、代理模式比较类似,但是又有不同。
和外观模式比较,中介者模式中,同事类必须依赖与中介者,中介者也知道同事类;但是外观模式中,子系统是不需要知道外观类的存在,并且子系统是可以脱离外观模式的。
和代理模式,代理模式的核心就是代理作用,主要还是对原先的类进行扩展或增加控制,比如进行权限控制;而中介者模式主要目的是为了减少对象之前的耦合,也就是同事类直接相互独立,互不影响。
23.解释器模式。
解释器模式的实现要点:
使用Interpreter模式来表示文法规则,从而可以使用面向对象技巧方便地“扩展”文法。
Interpreter模式比较适合简单的文法表示,对于复杂的文法表示,Interpreter模式会产生比较大的类层次结构,需要求助于语法分析生成器这样的标准工具。
解释器模式的主要优点有:
1】易于改变和扩展文法。
2】每一条文法规则都可以表示为一个类,因此可以方便地实现一个简单的语言。
3】实现文法较为容易。在抽象语法树中每一个表达式节点类的实现方式都是相似的,这些类的代码编写都不会特别复杂,还可以通过一些工具自动生成节点类代码。
4】增加新的解释表达式较为方便。如果用户需要增加新的解释表达式只需要对应增加一个新的终结符表达式或非终结符表达式类,原有表达式类代码无须修改,符合“开闭原则”
解释器模式的主要缺点有:
1】对于复杂文法难以维护。在解释器模式中,每一条规则至少需要定义一个类,因此如果一个语言包含太多文法规则,类的个数将会急剧增加,导致系统难以管理和维护,此时可以考虑使用语法分析程序等方式来取代解释器模式。
2】执行效率较低。由于在解释器模式中使用了大量的循环和递归调用,因此在解释较为复杂的句子时其速度很慢,而且代码的调试过程也比较麻烦。
在下面的情况下可以考虑使用解释器模式:
Interpreter模式的应用场合是Interpreter模式应用中的难点,只有满足“业务规则频繁变化,且类似的模式不断重复出现,并且容易抽象为语法规则的问题”才适合使用Interpreter模式。
1】当一个语言需要解释执行,并可以将该语言中的句子表示为一个抽象语法树的时候,可以考虑使用解释器模式(如XML文档解释、正则表达式等领域)
2】一些重复出现的问题可以用一种简单的语言来进行表达。
3】一个语言的文法较为简单.
4】当执行效率不是关键和主要关心的问题时可考虑解释器模式(注:高效的解释器通常不是通过直接解释抽象语法树来实现的,而是需要将它们转换成其他形式,使用解释器模式的执行效率并不高。)
spring中使用的设计模式
https://www.jb51.net/article/173348.htm
设计模式在各个开源框架中的运用
https://www.cnblogs.com/crazy-lc/p/11848893.html
https://baijiahao.baidu.com/s?id=1610737398997006908&wfr=spider&for=pc