变化是复用的天敌!
面向对象设计最大的优势在于:抵御变化!
参考前面的Shape1和Shape2实现。 |
以前面的Shape1为例,MainForm类依赖Line, Rect, Circle,这就是高层模块依赖低层模块,一旦低层模块有变化,则高层模块也要一并修改。MainForm的设计应该是稳定的,不能因为低层模块发生变化就变得不稳定。 而Shape2则是MainForm和Line, Rect, Circle等都依赖Shape抽象,这就隔离了变化,实现了两边都稳定的效果。 Shape抽象的设计不能与具体的实现细节绑定,也就是与Line, Rect, Circle等无关,不能引入依赖,否则就不稳定。 依赖倒置原则可用于检验大多数设计模式,解决依赖倒置的方法就是设计好抽象类,使其尽量稳定,以隔离变化。 |
已有的抽象要支持可扩展,也就是很方便地生成子类,以应对需求变化。 类模块应该是可扩展但不能修改的,比如前面的Shape2,在引入新的类时,不能修改原来已有的类。比如引入Circle类,则原来的Line和Rect都不能修改。 这里引入一个编码原则,当需求变化时,尽量通过增加代码的方式来应对需求,而不是修改现有代码以应对变化。 |
以Shape2为例,导致产生Line, Rect, Circle这些类的原因只有一个,那就是Draw方法不一样,这就是一个类应该仅有一个引起它变化的原因。很明显,Draw方法也是这些类的责任。 |
子类继承自父类时,不能导致父类的方法在子类里不能调用,这会违背了替换原则。如果子类不能替换父类,那就要重新考虑它们的关系,或许应该用组合而不是继承。 |
只给自己用的方法定义成private,只给子类用的方法定义成protected,只有给客户用的方法才定义成public。 |