在上篇博客里边我们说了单一职责原则,开放封闭原则和依赖倒置原则。今天我们说说里氏替换原则、迪米特原则、接口隔离原则和合成聚合复用原则。
里氏替换原则
定义:“派生类(子类)对象能够替换其基类(超类)对象被使用。”
含义:
- 子类必须完全实现父类的方法
- 在类中调用其他类时务必要使用父类或接口,如果不能使用父类或接口,则说明类的设计已经违背了里氏替换原则。
- 如果子类不能完整地实现父类的方法,或者父类的某些方法在子类中发生了“畸变”,则建议断开父子继承关系,采用依赖、聚集、组合等关系代替继承。
理解:子类可以扩展父类的功能,但不能改变父类原有的功能
里氏替换原则的核心精神是:在使用基类的的地方可以任意使用其子类,能保证子类完美替换基类;这一精神其实是对继承机制约束规范的体现。在父类和子类的具体实现中,严格控制继承层次中的关系特征,以保证用子类替换基类时,程序行为不发生问题,且能正常进行下去。
例子:比如说,在面向对象设计时,一个是鸟类,一个是企鹅类。在我们的常识中,企鹅是属于鸟的,按照正常的思维,企鹅类是可以继承鸟类的。但是按照里氏替换原则,子类必须能够替换掉他们的父类。而鸟类是可以飞的,而企鹅是不能飞的,企使得集成服用鹅类是替换不了鸟类的。也正是因为这个原则,使得继承复用成为了可能。只有当子类可以替换掉父类,软件单位的功能不受影响时,父类才能真正被复用,而子类也能够在父类的基础上增加新的行为。
推荐一篇博客:http://tonysmith.iteye.com/blog/1105622
迪米特原则
核心就是解耦,弱耦合能使类的复用率提高。
迪米特法则也叫做最少知识原则,就是一个对象对自己需要耦合关联调用的类应该知道的更少。这样会导致类之间的耦合度降低,每个类都尽量减少对其他类的依赖,因此,这也很容易使得系统的功能模块相互独立,之间不存在很强的依赖关系。
迪米特法则不希望和其他的类建立直接的接触;如果真的需要交互关系,也是希望通过自己比较熟的中间类来传达信息。比如中介者模式完美体现了迪米特原则,中介者模式的基本理论就是有一系列的对象,然后用一个中介对象来封装他们的交互,中介者与他们单独保持联系,个对象不需要显式的相互引用,从而使其耦合松散。
例子:比如国与国之间是需要相互通信的,任何一个国家都会与好多国家发生联系,如果一个国家出现变动,因为相互之间的联系不可避免的会影响到其他国家。但是联合国的建立,就相当于一个中介,国与国之间不需要直接发生联系,通过第三者联合国就好,这样的话,如果一个国家出现变动,也只是影响到联合国,不会影响其他更多的国家。
合成聚合复用原则
核心精神就是用组合聚合关系代替继承,保持较小规模,防止增长为不可控制的庞然大物。
例子:如果不同品牌手机的功能是互不兼容的
如果使用继承,代码如下:
手机品牌M继承手机品牌,手机品牌M的游戏继承手机品牌M,这样就感觉很臃肿,如果再增加手机品牌N和手机品牌N的功能软件,代码就会更加重复啰嗦。
如果使用合成聚合服用原则,代码如下
既可以按照品牌来分类,也可以按功能来分类。如果运用合成聚合复用原则,那么手机软件和手机品牌就不再是继承关系,而是手机软件是手机品牌的一个组成部分,这样就会减少类与类之间的耦合。
桥接模式就是合成聚合复用原则的最好体现,而桥接模式的核心意图就是把这些实现独立出来,让他们各自变化,然后手机功能和手机品牌实现组合。上面运用合成聚合原则的代码就是桥接模式的代码。
接口隔离原则
尽量使用多个专门的单一的小接口,避免庞大的总接口;专业点的说法是类间的依赖关系尽量建立在最小的接口上。
接口隔离原则和单一接口原则其实有一点相似,都是注重功能的单一。但是单一职责原则原注重的是职责;而接口隔离原则注重对接口依赖的隔离。
采用接口隔离原则对接口进行约束时,要注意以下几点:
• 接口尽量小,但是要有限度。对接口进行细化可以提高程序设计灵活性是不挣的事实,但是如果过小,则会造成接口数量过多,使设计复杂化。所以一定要适度。
• 为依赖接口的类定制服务,只暴露给调用的类它需要的方法,它不需要的方法则隐藏起来。只有专注地为一个模块提供定制服务,才能建立最小的依赖关系。
• 提高内聚,减少对外交互。使接口用最少的方法去完成最多的事情。
设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。每一种设计模式中最根本的理念就是这几种原则,而掌握这些原则最好的额方法就是:理解,实践,然后领悟。