一、什么是设计模式
这里引用克里斯托弗·亚历山大( Christopher Alexander)的一句话:
“每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心。
这样,你就能一次又一次地使用该方案而不必做重复劳动“
虽然克里斯托弗·亚历山大是一个建筑领域的专家,但这句话也能很完美的阐释设计模式的特点:解决重复问题、减少重复劳动,是一种解决方案的抽象,处理问题的模型。
设计模式的本质:通过分工协作实现复用性。
二、学习的要领
设计模式不是代码的精髓,而已一种思维的体现,学习过程中我们不能也不应该去纠结在代码的实现上,需要理解每一种的设计模式的思维模式,从更高的维度,更接近于生活的角度理解它们。
“举一而三反,闻一而知十,乃学者用功之深,穷理之熟,然后能融会贯通,以至于此。”
理解其本质之后,再繁琐的场景我们都能选择出恰当的设计模式去解决,再复杂代码我们也可以一眼看出编写思路。
三、重新认识面向对象
从代码的角度上理解面向对象,封装、继承、多态耳熟能详,今天我们要站在更高的维度去理解面向对象的好处。
理解隔离变化:
-
从宏观的角度来看,面向对象的构建方式更能适应软件的变化,能将变化所带来的影响减少为最小
各司其职
-
从微观的角度来看,面向对象的方式更强调各个类的“责任”。
-
由于需求变化导致的新增类型不应该影响原来类型的实现。
四、面向对象设计原则
1、依赖倒置原则(DIP)
-
高层模块(稳定)不应该依赖于低模块(变化),二者应该依赖于抽象(稳定)
-
抽象(稳定)不应该依赖于具体实现(变化),实现细节应该依赖于抽象(稳定)
2、开放封闭原则(OCP)
-
对扩展开放,对更改封闭
-
类模块应该是可扩展的,但是不可修改
3、单一职责原则(SRP)
-
一个类应该仅有一个引起它变化的原因
-
变化的方向隐含着类的责任
4、Liskov替换原则(LSP、里式代替)
-
子类必须能够替换它们的基类(IS-A)
-
继承表达类型抽象
5、接口隔离原则(ISP)
-
不应该强迫客户程序依赖它们不用的方法
-
接口应该小而完备
6、优先使用对象组合,而不是类继承(CRP、 合成复用原则)
-
类继承通常为“白箱复用”,对象组合通常为“黑箱复用“
-
继承在某种程度上破坏了封装性,子类父类耦合度高
-
对象组合则只要求被组合的对象具有良好定义的接口,耦合度低
7、封装变化点
-
使用封装来创建对象之间的分界层,让设计者可以在分界层的一侧进行修改,而不会对另一侧产生不良的影响,从而实现层次间的松耦合。
8、针对接口编程,而不是针对实现编程
-
不将变量类型声明为某个特定的具体类,而是声明为某个接口
-
客户程序无需获知对象的具体类型,只需要知道对象所具有的接口
-
减少系统中各部分的依赖关系,从而实现“高内聚、低耦合”
五、智慧的结晶源于生活
不难发现设计模式某种意义上,就是统一标准后、将各个分工协作的部门进行抽象,实现高度统一高度可靠的模型完成复用。结合生活和历史,来聊聊这样做的好处。
1、秦国的强大不仅是政治源于,还有更多的技术原因。我们聚焦于一点,考古的发现和史书的记载,秦国的兵器不论东南西北,出土地点都有统一标准,包括剑、戈、弩、箭,而其他的六国则不是。这样带来的好处所有的士兵的训练方式都有一样的,所有的箭适配所有的弩,战场上剑砍断了捡起一把不用适应直接可以使用。秦国做的事情便是把武器的“接口”统一了,各种武器都被抽象成了对象和标准。不仅是在武器方面,秦国更是统一了钱币,统一了度量衡。
2、活字印刷,统一了每一个字模板的大小,从而实现灵活的组合。非常典型的松耦合设计。