李建忠老师的思想:
①变化是复用的天敌。
②使用抽象的方法能够抵御变化。
多态调用,各负其责。
面向对象八大设计原则:
提醒:设计原则比模式更重要,懂得设计原则可以设计自己的设计模式
①依赖倒置原则(DIP)
依赖倒置原则十分的重要,几乎贯穿所有的设计模式。
①高层模块(稳定)不应该依赖于底层模块(变化),二者都应该依赖于抽象(稳定)。
如类MainForm属于高层模块,偏向于稳定,而Line、Circle属于低层模块,容易变化,第一版中的MainForm直接调用对Line、Circle做处理,使得稳定的东西依赖变化的东西,违背此原则,所以第二版中抽象出一个shape类,MainForm和circle、line中间隔着抽象的shape类,符合高层模块(稳定)与低层模块(变化)都依赖于抽象(稳定),可以达到隔离变化的目的。
②抽象(稳定)不应该依赖于实现细节(变化),实现细节应该依赖于抽象(稳定)。
有些人喜欢在抽象类中引用子类的方法。
抽象是稳定的,而实现细节是变化的,稳定的东西依赖于变化这就违背了依赖倒置原则。
有些人喜欢在抽象类中引用子类,这是不对的,违背依赖倒置原则的第二项。
核心思想:稳定的东西不应该依赖变化的东西,而应该变化的东西依赖于稳定的东西,依赖倒置原则实现了隔离变化。
②开放封闭原则(OCP)
①对扩展开放,对更改封闭。
②类模块应该是可扩展的,但是不可修改的。
例子:对于需求的变更,首先应该思考在原有的基础上做扩展,而不是直接推倒重来,开始可设计好通用性强的接口。
第二版MainForm以扩展的方式面对需求的变化。
③单一职责原则(SRP)
①一个类应该仅有一个引起它变化的原因。
②变化的方向隐含着类的责任。
解释:当我们一个类中有几十个方法的时候,类承担的责任变化过多,容易在几十个方向被拉扯,后面讲到桥模式、Decorate模式都会讲到类的责任的问题,类的责任在平时表现的没有那么明显,但是遇到特殊场合,便会发现考虑的稍有不慎便会产生棘手的问题。
④LisKov替换原则(LSP)
①子类必须能够替换它们的基类(IS-A)。
②继承表达类型抽象。
例子:子类继承父类的方法,然后子类在方法的重写中抛出异常,子类发生上述的子类替换父类时,直接就导致程序无法使用。
⑤接口隔离原则(ISP)
①不应该强迫客户依赖于它们不替换的方法。
②接口应该小而完备。
例子:父类的方法中,如果方法还在在子类使用,那方法的访问级别定义成public,如果只在父类中使用的方法做成private,不要无节制的将方法定义成public,会容易和调用方产生依赖。
⑥优先使用对象组合,而不是使用类继承
①类继承通常为“白箱复用”,对象组合通常为“黑箱复用”。
②继承在某种程度上破坏了封装性,父类可能会暴露过多的信息给子类,子类父类耦合度高。
③而对象组合则只要求被组合的对象具有良好定义的接口,耦合度低。
⑦封装变化点
①使用封装来创建对象之间的分界层,让设计者可以在分界层的一侧进行修改,而不会对另一侧产生不良的影响,从而实现层次间的松耦合。
理解:封装高层次的理解就是一侧稳定,一侧变化。
⑧针对接口编程,而不是针对实现编程
例如MainForm第二版的中已经将具体的类型都替换成shape类,使得可以使用shape的抽象接口。
②客户程序无需获知对象的具体类型,只需要知道对象所具有的接口。
③减少系统中各部分的依赖关系,从而实现“高内聚、松耦合”的类型设计方案。
理解:依赖倒置原则和针对接口编程原则相辅相成,违背依赖倒置原则就是违背接口编程原则,违背接口编程原则就是违背依赖倒置原则。
面向接口设计
接口标准化是产业强盛的标志,并不针对于软件行业。
一个产业如果能强盛,必然已经实现接口标准化,接口标准化的合作便是分工合作,通过分工合作才能实现复用性。
举例子:
①秦统一六国,如统一兵器长度,让兵器调配和士兵训练作战有统一标准,而燕国没做到。
②活字印刷取代雕版印刷