软件开发设计模式之【7】个【结构型】设计模式

代码码云仓库地址:https://gitee.com/dzxmy/design_pattern

常用的结构型设计模式有:适配器模式,装饰者模式,代理模式,外观模式,桥接模式,享元模式

不常用的结构型设计模式有:组合模式

一、外观模式

定义:又叫门面模式,提供了一个统一的接口,用来访问子系统中的一群接口,外观模式定义了一个高层接口,让子系统更容易使用

类型:结构型 

优点:简化了调用过程,无需了解深入子系统,防止带来风险,减少系统依赖,松散耦合,更好的划分访问层次,符合迪米特法则,即最少知道原则

缺点:增加子系统、扩展子系统行为容易引入风险,不符合开闭原则

com.dzx.design.structural.facade 包下代码:外观模式
 

二、 装饰者模式

定义:在不改变原有对象的基础之上,将功能附加到对象上,提供了比继承更有弹性的替代方案(扩展原有对象功能)

类型:结构型

适用场景:扩展一个类的功能或给一个类添加附加职责,动态的给一个对象添加功能,这些功能可以再动态的撤销

优点:

  • 继承的有力补充,比继承灵活,不改变原有对象的情况下,给对象一个扩展功能
  • 通过使用不同装饰类以及这些装饰类的排列组合,可以实现不同效果
  • 符合开闭原则

缺点:

  • 会出现更多的代码,更多的类,增加程序复杂性
  • 动态装饰时,多层装饰时
com.dzx.design.structural.decorator.v2 包下代码
 

三 、适配器模式

定义:将一个类的接口转换成客户期望的另一个接口 ,使原本接口不兼容的类可以一起工作

类型:结构型

使用场景:已经存在的类,它的方法和需求不匹配时(方法结果相同或类似) 

不是软件设计阶段考虑的设计模式,是随着软件维护,由于不同产品,不同厂家造成功能类似而接口不相同情况下的解决方案

优点:

  • 能提高类的透明性和复用,现有的类复用但不需要改变
  • 目标类和适配器类解耦,提高程序扩展性
  • 符合开闭原则

缺点:

  • 适配器编写过程需要全面考虑,可能会增加系统的复杂性
  • 增加系统代码的可读难度
com.dzx.design.structural.adapter 包下代码:适配器模式
 

 

四、享元模式

定义:提供了减少对象数量从而改善应用所需的对象的结构的方式

运用共享技术有效地支持 大量细粒度的对象

 类型:结构型

使用场景:常常应用于系统底层的开发,以便解决系统的性能问题,比如java种的String类,和数据库连接池

系统有大量相似的对象,需要缓冲池的场景。

优点:减少对象的创建,降低内存中对象的数量,降低系统的内存,提高效率,减少内存之外的其他资源占用 

缺点:关注内外部状态,关注线程安全问题,使系统,程序的逻辑复杂化

com.dzx.design.structural.flyweight 包下代码:享元模式
 

 五、组合模式

定义:将对象组合成树形结构以表示“部分-整体”的层次结构

组合模式使客户端对单个对象和组合对象保持一致的方式处理

类型:结构型

适用场景:

  • 希望客户端可以忽略组合对象与单个对象的差异时
  • 处理一个树型结构时

优点:清楚的定义分层次的复杂对象,表示对象的全部或部分层次,让客户端忽略层次差异,方便对整个层次结构进行控制,简化客户端代码,符合开闭原则。

缺点:限制类型时会较为复杂,使设计变得更加抽象

com.dzx.design.structural.composite 包下代码: 组合模式
 

六、 桥接模式

定义:将抽象部分与它的具体实现部分分离,使他们都可以独立地变化

通过组合的方式建立两个类之间联系,而不是继承

类型:结构型

适用场景:

  • 抽象和具体实现之间增加更多的灵活性
  • 一个类存在两个(或多个)独立变化的维度,且这两个(或多个维度都需要独立进行扩展)
  • 不希望使用继承,或因为多层继承导致系统类的个数剧增

优点:分离抽象部分及其具体实现部分,提高了系统的可扩展性,符合开闭原则,符合合成复用原则

缺点:增加了系统的理解与设计难度,需要正确地识别出系统中两个独立变化的维度

com.dzx.design.structural.bridge 包下代码:桥接模式
 

 七、代理模式

定义: 为其他对象提供一种代理,以控制对这个对象的访问

代理对象在客户端和目标对象之间起到中介的作用

适用场景:保护目标对象,增强目标对象

类型:结构型

优点:

  • 代理模式能将代理对象与真实被调用的目标对象分离
  • 一定程度上降低了系统的耦合度,扩展性好
  • 保护目标对象,增强目标对象

缺点:

  • 代理模式会造成系统设计中类的数目增加
  • 在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢
  • 增加系统的复杂度

分为静态代理 、 动态代理、CGLib代理

spring的代理选择

  • 当Bean有实现接口时,spring就会用jdk的动态代理
  • 当Bean没有实现接口时,spring使用cglib
  • 可以强制使用cglib,在spring配置中加入<aop:aspectj-autoproxy proxy-target-class="true"/>

参考资料:https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html

静态代理编码:

com.dzx.design.structural.proxy.staticproxy 包下代码 : 静态代理模式

 

动态模式编码:

com.dzx.design.structural.proxy.dynamicproxy 包下代码: 动态代理模式(核心:生成代理对象,重写InvocationHandler的invoke方法)
 

 

 

文章来源: blog.csdn.net,作者:血煞风雨城2018,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/qq_31905135/article/details/98054279

(完)