面向对象设计原则二

来源:互联网 发布:乐视mac码怎么查 编辑:程序博客网 时间:2024/05/02 04:16
  1. 单一职责原则(SRP):一个类应当只有一个改变的原因,类只需要知道一件事情,它们应当有一个单独的职责,要点就是当一个类需要改变时,应当只有一个原因。
  2. 开放-封闭原则(OCP):软件实体(类、模块、函数等)应当为扩展而开放,又为修改而封闭。这个原则有一个相当详细的定义,但是一个简单的意思是:你应当能够改变一个模块的周边环境而无须改变模块本身。
  3. Liskov替换原则(LSP):子类型(subtypes)必须是为它们的基类型(base types)可替代的。
  4. 依存关系倒置原则(DIP) :A.高层模块应当不依赖低层模块,它们应当依赖于抽象。
    B.抽象应当不依赖于细节,细节应当依赖于抽象。
    更好的描述是:不要依赖那些容易变化的具体类。如果你要继承一个类,从一个抽象类继承吧。如果你要持有一个类的引用,从一个抽象的类引用吧。如果你要调用一个函数,从一个抽象的函数调用吧。
  5. 接口隔离原则(ISP):客户不应当依赖那些它们根本不用的方法。

总结:
五个简单的原则是:
1、SRP--一个类应当只有一个发生变化的原因。
2、OCP――应当能够改变一个类的环境,而无须改变类本身。
3、LSP――避免造成派生类的方法非法或退化,一个基类的用户应当不需要知道这个派生类。
4、DIP ――用依赖于接口和抽象类来替代依赖容易变化的具体类。
5、ISP――给一个对象的每一个用户一个接口,这个接口仅有用户需要的方法。


正如牛顿三大定律在经典力学中的位置一样,“开-闭”原则(Open-Closed Principle)是面向对象的可复用设计(ObjectOrientedDesign或OOD)的基石。其他设计原则(里氏代换原则、依赖倒转原则、合成/聚合复用原则、迪米特法则、接口隔离原则)是实现“开-闭”原则的手段和工具。
  一、“开-闭”原则(Open-Closed Principle,OCP)
   1.1“开-闭”原则的定义及优点
  1)定义:一个软件实体应当对扩展开放,对修改关闭( Software entities should be open forextension,but closed formodification.)。即在设计一个模块的时候,应当使这个模块可以在不被修改的前提下被扩展。
  2)满足“开-闭”原则的系统的优点
  a)通过扩展已有的软件系统,可以提供新的行为,以满足对软件的新需求,使变化中的软件系统有一定的适应性和灵活性。
  b)已有的软件模块,特别是最重要的抽象层模块不能再修改,这就使变化中的软件系统有一定的稳定性和延续性。
  c)这样的系统同时满足了可复用性与可维护性。
  1.2如何实现“开-闭”原则
  在面向对象设计中,不允许更改的是系统的抽象层,而允许扩展的是系统的实现层。换言之,定义一个一劳永逸的抽象设计层,允许尽可能多的行为在实现层被实现。
  解决问题关键在于抽象化,抽象化是面向对象设计的第一个核心本质。
  对一个事物抽象化,实质上是在概括归纳总结它的本质。抽象让我们抓住最最重要的东西,从更高一层去思考。这降低了思考的复杂度,我们不用同时考虑那么多的东西。换言之,我们封装了事物的本质,看不到任何细节。
  在面向对象编程中,通过抽象类及接口,规定了具体类的特征作为抽象层,相对稳定,不需更改,从而满足“对修改关闭”;而从抽象类导出的具体类可以改变系统的行为,从而满足“对扩展开放”。[Page]
  对实体进行扩展时,不必改动软件的源代码或者二进制代码。关键在于抽象。
  1.3对可变性的封装原则
  “开-闭”原则也就是“对可变性的封装原则”(Principle of Encapsulation of Variation,EVP)。即找到一个系统的可变因素,将之封装起来。换言之,在你的设计中什么可能会发生变化,应使之成为抽象层而封装,而不是什么会导致设计改变才封装。
   “对可变性的封装原则”意味着:
  a)一种可变性不应当散落在代码的许多角落,而应当被封装到一个对象里面。同一可变性的不同表象意味着同一个继承等级结构中的具体子类。因此,此处可以期待继承关系的出现。继承是封装变化的方法,而不仅仅是从一般的对象生成特殊的对象。
  b)一种可变性不应当与另一种可变性混合在一起。作者认为类图的继承结构如果超过两层,很可能意味着两种不同的可变性混合在了一起。
  使用“可变性封装原则”来进行设计可以使系统遵守“开-闭”原则。
  即使无法百分之百的做到“开-闭”原则,但朝这个方向努力,可以显著改善一个系统的结构。
  二、里氏代换原则(Liskov Substitution Principle, LSP)
  2.1概念
  定义:如果对每一个类型为T1的对象O1,都有类型为T2 的对象O2,使得以T1定义的所有程序P在所有的对象O1都代换为O2时,程序P的行为没有变化,那么类型T2是类型T1的子类型。
  即,一个软件实体如果使用的是一个基类的话,那么一定适用于其子类。而且它觉察不出基类对象和子类对象的区别。也就是说,在软件里面,把基类都替换成它的子类,程序的行为没有变化。
  反过来的代换不成立,如果一个软件实体使用的是一个子类的话,那么它不一定适用于基类。
  任何基类可以出现的地方,子类一定可以出现。
  基于契约的设计、抽象出公共部分作为抽象基类的设计。
  2.2里氏代换原则与“开-闭”原则的关系
   实现“开-闭”原则的关键步骤是抽象化。基类与子类之间的继承关系就是抽象化的体现。因此里氏代换原则是对实现抽象化的具体步骤的规范。
   违反里氏代换原则意味着违反了“开-闭”原则,反之未必。
  三、 依赖倒转原则(dependence inversion principle, DIP)
   3.1概念
   依赖倒转原则就是要依赖于抽象,不要依赖于实现。(Abstractions should not depend upon details.Details should depend upon abstractions.)要针对接口编程,不要针对实现编程。(Program toan interface, not an implementation.)
  也就是说应当使用接口和抽象类进行变量类型声明、参数类型声明、方法返还类型说明,以及数据类型的转换等。而不要用具体类进行变量的类型声明、参数类型声明、方法返还类型说明,以及数据类型的转换等。要保证做到这一点,一个具体类应当只实现接口和抽象类中声明过的方法,而不要给出多余的方法。
  传统的过程性系统的设计办法倾向于使高层次的模块依赖于低层次的模块,抽象层次依赖于具体层次。倒转原则就是把这个错误的依赖关系倒转过来。

 

原创粉丝点击