设计模式总述
# 工作中常用的模式
# 创建型
- 建造者 : 有builder,做入口解析、链式调用代替set方法。
- 工厂方法 : 封装new细节。
# 结构型
- 适配器 : 用接口+引用+封装, 做第三方的整合进入现有系统。
- 装饰器 : 用向上循环委托 , 做显式的功能增强
- 代理 : 用静态委托、jdk/字节码动态代理,做隐式的功能增强
- 组合 : 用循环所有,做树状结构的逻辑处理。
- 外观/门面 : 用多种委托,做所有的入口操作。
# 行为型
- 策略, 用不同实现类 ,代替switch、if-else(说成switch更类似)
- 组合 , 用循环+跳出条件 ,代替if-else
- 状态 , 用对象和上下文入参 , 代替if-else + 状态流转
- 模板 , 用抽象类,定义主体流程。
- 责任链 , 用循环或者递归,代替对上下文的流程化加工
- 观察者, 用循环+回调, 实现发布/订阅的业务解耦。
# 常见的23种设计模式
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
其实还有两类:并发型模式和线程池模式。
# 简单工厂模式
主要解决接口/实现类选择的问题
我们明确地计划不同条件下创建不同实例时使用,同时封装了new 对象的过程。
屏蔽了选择类和创建类的步骤,用户只管使用就行了。
# 实现模式
- Factory.get(xxx);
- Factory.get();
# 框架中的实现
- 日志记录器LogFactory.getLog
- spring中的BeanFactory . 有些地方把他叫做抽象工厂,不太正确。
- jdbc中的DriverManager.getConnection
- jdk中的日历 Calendar.getInstance()
# 参考资料
设计模式之简单工厂模式(Simple Factory Pattern) (opens new window)
# 工厂方法模式
- 主要解决: 延迟实例化类;解耦使得工厂符合开闭原则。
- 工厂方法进一步解耦合,把工厂类抽象,不再负责所有实例的创建,而是把具体的创建工作交给了子类去完成,实例化延迟到子类加载,由子类来决定要实例化的类。
# 实现模式
# 依赖的实现方式
超级工厂、工厂、产品.
超级工厂获得工厂,工厂再获得产品
# 继承实现
- 抽象工厂类、具体的工厂类、产品
# 框架中的实现
- spring中的FactoryBean功能
# 抽象工厂
- 是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。
- 主要解决: 针对的是界线划分; 主要针对的是多个产品族结构,一个产品族内有多个产品系列
# 实现模式
- 抽象工厂、抽象产品,具体工厂,具体产品
- 各自工厂产出各自的产品。
- 一般还会和组合模式配合,提供确定具体工厂的方法,已达到简化客户端使用。 (如jdbc中的DriverManager.getConnection)
# 框架中的实现
- jdbc中的Connection
# 参考资料
抽象工厂在Java源码中的应用 (opens new window)
# 单例模式
保证一个类仅有一个实例,并提供一个访问它的全局访 问点。
# 实现模式
- 恶汉模式
- 懒汉模式: 双重判断加锁 spring中的getSiglenBean
# 建造者模式
# 原型模式
# 桥接模式
# 过滤器模式
# 外观模式
# 享元模式
# 代理模式
隐式(对于用户无感知)的用于控制访问权限、和增加功能。
# 实现方式
- 静态代理模式 : 父类继承的方式。
- jdk动态代理模式
- cglib动态代理模式
# 框架中的实现
- spring中的AOP
- mybatis中的mapper就是jdk代理
- Fegin 的接口代理.
# 装饰器模式
- 显式(也就是说用户需要自己主动去选择)的用于控制访问权限、和增加功能。
- 和代理模式,继承不同的是,他侧重于交给用户去选择组合内容,增强顺序。
# 实现模式
基础类、增强类都实现相同接口。在增强类的构造方法中传入接口,再不同的方法中调用传入的接口
# 框架中的实现
- spring中类名带Wrapper、Decorator的。
- jdk中的IO流
# 命令模式
# 解释器模式
# 迭代器模式
# 中介者模式
# 备忘录模式
# 观察者(监听者)模式
# 实现模式
事件广播器(EventMulticaster),事件(Event),事件监听器(Listener).
一般是广播器中有个list,用于存放监听器。当调用广播器的方法时,就循环发送给监听器。
# 框架中的实现
- spring-boot的 SpringApplicationRunListener 启动过程的接口回调,主要用于解耦.
- spring中的 ApplicationListener 用于解耦不同服务,异步调用,通知
# 状态模式
# 空对象模式
#
# 模板模式
定义主流程,其他的流程交给子类去实现.
主要解决:一些方法通用,却在每一个子类都重新写了这一方法。
使用场景: 1、有多个子类共有的方法,且主体逻辑相同。 2、重要的、复杂的方法,可以考虑作为模板方法。
**注意事项:**为防止恶意操作,一般模板方法都加上 final 关键词。
# 实现模式
- 定义abstract 类,方法定义为final,预留一些扩展点(默认实现),抽象的操作交给子类去实现(abstract 方法).
- 尽可以抽象成多的方法,交给子类去做增强扩展。
# 框架中的实现
- 所有框架中带有abstract 类中定义了主流程,多个子类的都是,数不胜数。
# 回调模式
模板模式的应用场景一致,属于升级版本,主要是利用接口回调去实现,这样可以不用管具体是那个子类了,主体类就是固定的了。实现了业务逻辑和主体代码的分离和解耦。
和模板模式的不同在于: 我的主体逻辑肯定不会变,不需要子类做一些自定义的扩展操作,同时我的业务逻辑类似能抽象出来。 也就是说大部分应用场景都是已知的只是做了代码提取。
# 框架中的实现
- spring框架中的 XXXTemplate,就是回调模式去实现的。
# 访问者模式
# MVC 模式
# 业务代表模式
# 组合实体模式
# 数据访问对象模式
# 前端控制器模式
# 拦截过滤器模式
# 服务定位器模式
# 传输对象模式
# 策略模式
# 实现模式
# 框架中的实现
- springmvc
HandlerMethodMappingNamingStrategy : MappingRegistry中通过name获得HandlerMethod
ContentNegotiationStrategy : 内容协商策略
- spring 中的 Resource实现了好多自定义的资源访问协议,如classpath: , fatJar
# 责任链模式
工厂流水线中的工序加工 : 每道工序都对同一个物品做操作,做完自己的后传递给下一道工序。 从而实现了功能单一职责.
# 实现模式
- super.xxx(); 同一个方法,一直到头、每个类处理一件事。
- for循环调用.
# 框架中的实现
- springmvc : RequestBodyAdvice、RequestBodyAdvice、HandlerInterceptor
- Servlert : 请求转发、过滤器
- spring : aop中定义的 MethodInterceptor
# 适配器模式
将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
主要是转化,也就是说自己真正核心的功能是其他类实现的。
应用场景 :
- 让任何两个没有关联的类一起运行
- 接口转换: 转化一些第三功能,为自己系统定义的标准接口.
- 将一个类的接口转换成客户希望的另外一个接口。
# 实现模式
- 简单转化单一类,继承 + 实现要转化的接口。
- 复杂的要转化多个类组合现实某一功能, 用属性依赖。
# 框架中的实现
- springmvc : HandlerAdapter
# 组合模式
- 策略模式的变种,通过判断方法确定该类,是否执行真正的方法. 来选定具体的策略. 适用于复杂的策略选定。
- 实现2叉树数值的计算的场景. 经典场景就是购物袋和商品的总价计算模型。
# 框架中的实现
- spring-mvc 中的 : argumentResolvers,returnValueHandlers,modelAndViewResolvers,messageConverters,handlerMappings,HandlerAdapters,HandlerExceptionResolvers,ViewResolvers ,WebMvcConfigurerComposite 他们这些类都提供2个方法,一个判断方法,一个是真正运行方法。
# 委托模式
核心类负责分配和调度,或者是判断类型的安全。
# 框架中的实现
springmvc : DelegatingWebMvcConfiguration委派配置类,用于收集所有的WebMvcConfigurer
spring中的SourceFilteringListener,做了source的监听分配,确保安全。
# 参考资料:
常用的23种设计模式中其实面没有委派模式(delegate)的影子,但是在 Spring 中委派模式确实用的比较多 (opens new window)
在委托模式实现过程中,有两个对象参与处理同一个请求,接受请求的对象将请求委托给另一个对象来处理。
通过使用接口,委托可以做到类型安全并且更加灵活。
# 参考资料
jdbc使用到了哪些设计模式 (opens new window)
深入理解JDBC设计模式: DriverManager 解析 (opens new window)