设计模式复习小结
1.容易忘得设计原则
接口隔离:指接口中的功能太杂则可以拆分一下。防止实现类实现了接口后自动依赖了一些不需要的功能。不同功能拆分成不同的接口。
里氏代换:强调父类能出现的地方,子类一定能正常跑。
迪米特法则:又称最少知识原则,只与直接朋友通信,提高模块独立性。
单一职责,合成复用,开闭原则
依赖倒转: 指聚合/组合时使用抽象而非具体的子实现类。对抽象编程。降低客户与实现模块之间的藕合。“父类引用指向子类对象” 这说明 依赖倒转结合使用了里氏代换原则。
2、控制反转,指我写了一套抽象的支付代码,spring帮我去管理是阿里支付还是微信支付。
这个概念建立在依赖倒转原则上。即编码基于抽象。
依赖倒转是说我依赖的时候不依赖具体实现了,我依赖倒转了,变成了依赖抽象。控制反转强调的是谁创建对象。比如由容器进行构造器注入,setter注入等。
我先依赖倒转,依赖抽象支付工具,写抽象代码,然后控制反转注入bean交给spring。这样我的工作就大大简化。不需要自己去太多关注支付方式。
3.关于适配器模式 与 桥接模式的联系与区别。
适配器的典型用法: 事后补救,解决接口不兼容的问题。
class Adapter implements NewInterface {
private LegacyClass legacyObj;
适配器类实现新接口,但是组合老的实现类。通过老的实现类的方法作为input,经过一定的转换,来返回新接口方法格式的结果。
桥接模式的典型用法:事前规划。选取一个主维度作为主体,去组合其他的维度。
抽象层与实现分离。比如统一的UI框架与不同OS的渲染。统一的数据格式与不同的db 驱动。
或者是多维度的分离,防止类爆炸。比如形状与颜色,车的类型与引擎的类型。
二者也经常结合使用。比如桥接模式定义一个抽象层,如数据存储,然后组合一个Adaptor类型的实现层。
这样在实现一个具体数据存储的时候,可以去组合不同驱动类型的adaptor。
回过头来,简单总结,这个桥接模式就是用抽象组合抽象。从而减少类定义的复杂度。
4.关于单一职责原则和接口隔离原则的练习与区别。
两者都体现了高内聚,低耦合理念。
但是单一职责强调类的职责,比如订单类与支付类的拆分。
接口隔离原则强调接口的拆分,比如飞行功能与汽车行驶的接口功能拆分。
5.访问者模式:
一句话总结: 不想在猫,狗类中写关于 健康检查,喂食等代码。
简单写一个accept 方法。调用入参的Visit。
具体的健康检查,喂食,由入参类负责。
另外一般会有一个动物园类来组合元素集合。并提供依次accept的方法。方便兽医、喂食人员调用。
适合于你有一堆类似的元素(猫狗等),然后你又想将来以不同的方式来批量对待他们。
精髓是将操作从数据结构中分离出来,适用于操作易变,但数据结构稳定的系统。比如编译器,UI框架。
规避场景:数据结构容易变,或者不可预知的场景。即猫狗易变,而且我也不知道啥时候集合里面会多来一种动物。
备忘录类 典型例子是游戏存档
存储游戏状态快照,但是不想让其他人访问,随意修改数据。
Momento 对象,对其他人如玩家提供窄接口,仅对发起人(游戏程序员、GM、或者是数据敏感的GAMEROLE类这样的角色等)提供宽接口。
在java中的实现方案是,将PrivateMomento 设计为 GM类的成员内部类。
GM对外提供的backup restore 都是Momento类型。实际GM进行操作时,强转为PrivateMomento再在内部方法中偷偷操作属性等。
精髓:针对同样一个操作,实现双接口。对不同类暴漏的功能数量不一样。增强安全性。
对于无关的人,我给你一个功能很少的接口类。等到了底层真正执行的时候,你会发现它强转了向下转型了另外一个功能更强大的类。
7.状态模式
把状态抽象成类,对于同一个方法,当前是什么状态干什么事,减少if else 的使用。
比如向前Go订单。-> 现在是下单那就发货,是发货那就签收。