
技能篇:实际开发常用设计模式
创建型
单例模式
单例对象能节约系统资源,一个对象的创建和消亡的开销可能很小。但是日常的服务接口,就算是一般小公司也有十几万的QPS吧。每一次的功能运转都创建新的对象来响应请求,十几万对象的创建和销毁,想想就是一笔大开销,所以 spring 管理构造的 bean 对象一般都是单例。而且单例模式可以更好的解决并发的问题,方便实现数据的同步性
- 优点
○ 在内存中只有一个对象,节省内存空间
○ 避免频繁的创建销毁对象,可以提高性能
○ 避免对共享资源的多重占用,简化访问
○ 为整个系统提供一个全局访问点
- 缺点
○ 不适用于变化频繁的对象
工厂模式
使用者不关心对象的实例化过程,只关心对象的获取。工厂模式使得产品的实例化过程和消费者解耦
- 优点
○ 一个调用者想创建一个对象,只需通过其名称或其他唯一键值在工厂获取
○ 扩展性高,如果想增加生产一种类型对象,只要扩展工厂类就可以
- 缺点
○ 工厂类不太理想,因为每增加一产品,都要在工厂类中增加相应的生产判断逻辑,这是违背开闭原则的
建造者模式
主要解决在软件系统中一个复杂对象的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定
- 优点
○ 扩展性好,对象每一个属性的构建相互独立,有利于解耦。
○ 建造者可以对创建过程逐步细化,而不对其它模块产生任何影响,便于控制细节风险
- 缺点
○ 如果对象建造者发生变化,则建造者也要同步修改,后期维护成本较大
○ 一种建造者对应一种类型建造,一个建造者基本很难建造多种类型对象
结构型
适配器模式
连通上下游功能。一般是现有的功能和产品要求的接口不兼容,需要做转换适配。平时见到的 PO,BO,VO,DTO 模型对象之间的相互转换也是一种适配的过程
- 优点:提高了类的复用,灵活性好
- 缺点:过多地使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是 A 接口,其实内部被适配成了 B 接口的实现
装饰器模式
增强对象功能,动态的为一个对象增加功能,而且还能动态撤销。(继承不能做到这一点,继承的功能是静态的,不能动态增删)
代理模式
代理类是客户类和委托类的中介,可以通过给代理类增加额外的功能来扩展委托类的功能,这样只需要修改代理类而不需要再修改委托类,符合代码设计的开闭原则
- 和装饰器模式的区别:代理模式着重于增强类功能,且对面屏蔽原对象的创建过程;装饰器模式增强的是对象,且装饰器模式有一个动态传递原对象的步骤
- 和对象的适配器模式优点像:不过代理模式着重的是对原功能增强,适配器模式着重的是对新功能的兼容
- 优点-1、职责清晰。2、高扩展性
桥接模式
桥接模式侧重于功能的抽象,从而基于这些抽象接口构建上层功能。一般的java 项目都会将接口和实现分离原因,就是基于桥接模式。提高了系统的扩展能力,当引用的底层逻辑有不同的设计实现时,继承抽象接口重新实现一套即可,旧的不变,符合代码设计的开闭原则
- jdbc 的驱动:常用的JDBC 和 DriverManager,JDBC进行连接数据库的时候,在各个数据库之间进行切换,基本不需要动太多的代码,原因就是JDBC提供统一接口,每个数据库提供各自的实现,用一个叫做数据库驱动的程序来桥接
- Unix 的文件系统:VFS(virtual File System)使得 Unix 系统可以在不同物理介质上的不同文件系统进行读写
- 可配合适配器模式使用
享元模式
多个对象共享某些属性。在创建有大量对象时,可能会造成内存溢出,把其中共同的部分抽象出来,如果有相同的请求,直接返回在内存中同一份属性,避免重新创建
- 如 jdbc 连接池的连接对象,它们会共享池对象的 url、driverClassName、username、password 等属性
外观模式
- 用多个不同的对象实现一组更复杂的功能。使得类与类之间的关系解耦。如 spring 将使用各个简单的 component、dao 实现复杂的service,就是一种外观模式
- 功能的组合,组合优于继承
行为型
策略模式
策略模式侧重于不同的场景使用不同的策略。在有多种算法相似的情况下,解决 if...else 所带来的复杂和难以维护
- 和桥接模式的区别:而桥接模式是结构型模式,侧重于分离底层功能的抽象和实现,底层只有一种实现也可以
模板方法
和享元模式有一定的相似处,享元模式侧重于属性的共享,而且是结构上的引用,不一定需要继承;而模板方法是共享相同行为,一定有继承行为
- 区别于策略模式是它有能抽象出来的共同行为,每一个子类再实现有差异细节
迭代子模式
循环处理多个相同对象,用来遍历集合或者数组
责任链模式
负责处理上游的传递下来的对象,并传递给下一个处理者
- 和迭代子模式的区别,责任链模式是多个hander处理同一个data,且 hander 处理具有顺序性,不用全部 hander 处理,可在某一 hander 中断,也可继续传递
观察者模式
事件通知: 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知
- 优点:观察者和被观察者是抽象耦合的
- 缺点
○ 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间
○ 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃
状态机模式
不同的状态不同的响应,实现状态之间的转移
- 和策略模式的区别
○ 状态机模式是策略模式的孪生兄弟。策略模式可以让用户指定更换的策略算法,而状态机模式是状态在满足一定条件下的自动更换,用户无法指定状态,最多只能设置初始状态
○ 状态机模式重点在各状态之间的切换,从而做不同的事情;而策略模式更侧重于根据具体情况选择策略,并不涉及切换
备忘录
记录上一次的状态,方便回滚。很多时候我们是需要记录当前的状态,这样做的目的就是为了允许用户取消不确定或者错误的操作,恢复到原先的状态
- 缺点:消耗资源。如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存
文章转载自公众号:潜行前行
