设计模式
2021-11-21 19:43:24 0 举报
设计模式定义,SOLID原则, 创建型模式:工厂模式,建造者模式,原型模式 结构型模式:享元模式,门面模式,适配器模式,装饰者模式,组合模式 行为型模式:观察者模式
作者其他创作
大纲/内容
定义
在软件设计中,被反复使用的代码设计经验,目的是提高系统的可维护性和扩展性
原则(SOLID)
单一职责原则Single Responsibility Principle(SRP)
定义
一个类应该只有一个变化的原因
开闭原则Open Closed Principle(OCP)
定义
对扩展开发,对修改关闭
里氏替换原则Liskov Substitution Principle(LSP)
定义
所有引用基类的地方必须能透明地替换成子类
依赖倒置原则Interface Segregation Principle(ISP)
定义
高层模块不应该依赖底层模块,二者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象
接口隔离原则Dependence Inversion Principle(DIP)
定义
客户端不应该依赖它不需要的接口,对一个类的依赖应该建立在最小接口上
和单一职责的区别
单一职责强调职责隔离,针对具体实现类,接口隔离原则强调接口规范设计
迪米特法则(最少知道原则)
定义
一个对象应该对其他对象保持最少的了解
实现
只与直接朋友通信,不与陌生人通信
陌生的类不要出现以局部变量的形式中出现在类的内部
创建型模式
单例模式
工厂方法
定义
定义一个创建对象的接口,让子类决定实例化哪个类,使对象的创建延迟到子类<br>
场景
当一个类不知道它所必须创建的对象的类的时候<br>
当一个类希望由它的子类指定它所创建的类的时候<br>
抽象工厂模式
定义:提供一个创建一系列相关或互相依赖对象的接口,而无需指定它们具体的类<br>
场景
程序需要处理<b>不同系列</b>的<b>相关</b>的产品,但又不希望依赖其中具体的实现类时<br>
优点
可以确信从工厂得到的产品是彼此兼容的
避免具体产品与客户端代码的紧密耦合<br>
单一职责原则
开闭原则
应用<br>
java.sql.connection
java.sql.driver
建造者模式
定义:将一个复杂对象与它的表示分离,使同样的构建过程可以创建不同的表示<br>
场景
建造复杂对象
对象的字段有依赖关系
不可变对象
优点
建造者独立,易扩展,开闭原则
便于控制细节风险
应用
spring的RequestMappingInfo
BeanDefinitionBuilder
原型模式
定义
使用原型指定待创建对象的类型,并通过复制这个原型来创建新的对象
实现方式
实现Cloneable接口,重写Object.clone()
序列化机制
应用场景
当代码不需要依赖复制对象的具体类的时候<br>
优点
可以在不耦合具体类的情况下复制对象<br>
避免重复的对象创建代码
更方便的创建复杂对象<br>
结构型模式
享元模式
定义
运用共享技术来支持大量细粒度的对象
场景
如果系统中有大量<b>相同类型的不可变对象</b>,那么可以将它们缓存起来,避免重复创建占用CPU和内存资源
应用
包装类型缓存
String字符串常量池
数据库缓存
优点
避免了大量对象的重复创建,节省系统资源,提高响应速度
门面(外观)模式
定义
为子系统的一组接口提供一个一致的界面,Facade模式定义了一个简单的视图,使得子系统更容易使用<br>
场景
微服务网关
优点
减少了客户需要交互的子系统数量,简化了子系统的使用
客户端不与具体子系统耦合,而是与门面耦合,可以较为方便的升级子系统而尽量不影响客户端
适配器模式
定义
将一个类的接口转换为客户希望的另一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作
是一种补救措施
场景
复用一个控制之外的原有对象,但接口与复用环境不一致<br>
通常在维护阶段,不太容易修改的时候使用
设计之初,如果要用第三方组件,但接口不兼容,又不好修改自身接口<br>
装饰者模式
定义
在不改变原有类的基础上,将功能附加到对象上,就修改来说,比生成子类更加灵活<br>
参与者
优点
相比于静态继承,可以在运行期动态添加和删除职责<br>
继承需要为每个职责添加一个子类,避免了继承体系的臃肿
为一个Component提供多个Decorator,这使得你可以对职责进行混合和匹配<br>
缺点
产生许多相似的小对象,很难学习这个系统,难以排错
注意
接口一致性,装饰和组件应该有一个公共的父类<br>
省略抽象的Decorator,如果只有一个ConcreateDecorator
接口简单性<br>
组件过于庞大时,装饰者代价太高,可以考虑策略模式
和strategy的区别
decorator模式,装饰者对组件是透明的,组件不需要了解装饰者
strategy,组件知道可以对自己的哪些行为进行扩充,因此它必须引用并维护相应的策略<br>
装饰者必须与组件有公共的接口,策略不需要
与适配器的区别
装饰者只改变对象的职责,而不改变接口,适配器提供了全新的接口
组合模式
定义
将对象组合成树形结构以表示“部分-整体”的关系,使得用户对单个对象和组合对象的使用具有一致性<br>
实现
优缺点
简化客户端代码
更容易添加新的组件
不好限制组合中组件的类型,只能在运行时检查<br>
行为型模式
观察者模式(发布-订阅模式)<br>
定义了一种一对多的对象依赖关系,当一个对象的状态发生改变,关联的对象都得到通知并被自动更新
一个目标可以有任意数目的观察者,它发出通知时并不需要知道它的具体观察者是谁<br>
参与者
目标Subject
目标知道它的观察者,可以有任意多个观察者
提供注册和删除观察者的接口, 以及一个通知接口notify
观察者Observer
提供一个目标发出通知时更新自身的接口update
ConcreteSubject
具体目标存储了各自的状态,并在状态发生改变时通知与其关联的观察者
ConcreteObserver
维护了它关联的Subject的引用,和相应的状态,并提供一个更新方法以保持自身状态与目标状态一致<br>
观察者通过查询目标的状态,来更新自己的状态
目标状态的变化可以由其中一个观察者发出,观察者先不更新自身状态,而是先更新目标状态,从而调用notify方法更新所有观察者的状态<br>
优缺点<br>
支持广播通信,目标发送通知不需要指定它的接收者,通知被自动广播给已向该目标注册的所有观察者,可以在任意时刻增加和删除观察者,处理一个通知取决于观察者<br>
缺点:因为一个观察者不知道其他观察者的存在,它对目标的更新可能会引起一系列对观察者以及相关联对象的更新,如果依赖准则处理不当可能会引起错误的更新<br>
实现
如果目标很多,观察者很少,为了避免每个目标都维护对应观察者的引用造成空间浪费,可以用hash表维护目标到观察者的映射,这样没有观察者的目标就不占用任何存储空间<br>
观察者可以观察多个目标,这样的话update方法的参数就要加目标参数,以便知道是哪个目标状态更新了。或者提供一个获取状态更新的目标集合的方法,比如NIO selector
调用notify的时机: 1、目标每次状态更新都触发一次notify通知,这样客户端使用简单,但是容易导致频繁通知。2、由客户端调用notify,这样不会导致不必要的通知,但增加了使用难度,可能会遗漏触发通知
通知的时候要注意,必须在目标状态一致时通知
通知的方式有推模式和拉模式<br>
推模型
目标向观察者发送更新的状态信息,通常是在update参数中定义
需要目标假定观察者需要哪些信息,这使得观察者可能难以复用<br>
拉模型
目标只告诉观察者状态更新了,具体更新信息需要观察者再向目标查询获得
强调的是目标不知道它的观察者,观察者更易于扩展,但效率较差,因为观察者需要在没有目标帮助的情况下获取什么状态改变了<br>
为了提高更新的效率,可以在注册观察者时指定它感兴趣的事件,notify方法参数增加事件参数,特定事件触发时,只通知对事件感兴趣的观察者<br>
0 条评论
下一页