设计模式的六大原则
单一职责原则(Single Responsibility Principle, SRP)
单一职责原则是最简单的面向对象设计原则,它用于控制类的粒度大小。
定义如下:
一个类只负责一个功能领域中的相应职责,或者可以定义为:就一个类而言,应该只有一个引起它变化的原因。
遵循单一职责原则的优点有:
- 可以降低类的复杂度,一个类只负责一项职责,其逻辑肯定要比负责多项职责简单得多;
- 提高类的可读性,提高系统的可维护性;
- 变更引起的风险降低,变更是必然的,如果单一职责原则遵循的好,当修改一个功能时,可以显著降低对其他功能的影响。
里氏替换原则(Liskov Substitution Principle, LSP)
里氏替换原则(Liskov Substitution Principle, LSP)是面向对象设计的基本原则之一。
定义1:如果对每一个类型位T1的对象o1,都有类型为T2的对象o2,使得以T1定义的所有程序P在所有的对象o1都代换成o2时,程序P的行为没有发生变化,那么类型T2是类型T1的子类型。
定义2:所有引用基类的地方必须能透明地使用其子类的对象。
通俗简单的说,子类可以扩展父类的功能,但不能改变父类原有的功能。
里氏替换原则包含以下4层含义:
- 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
- 子类中可以增加自己特有的方法。
- 当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。(注意区分重载和重写)
- 当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。
依赖倒置原则(Dependence Inversion Principle, DIP)
依赖倒置原则(Dependence Inversion Principle)就是要依赖于抽象,不要依赖于具体。实现开闭原则的关键是抽象化,并且从抽象化导出具体化实现,如果说开闭原则是面向对象设计的目标的话,那么依赖倒转原则就是面向对象设计的主要手段。
定义:高层模块不应该依赖低层模块,二者都应该依赖抽象;抽象不应该依赖细节;细节应该依赖抽象。
通俗地说,要求对抽象编程,不要对实现编程,这样就降低了客户与实现模块间的耦合。
依赖倒置原则的核心思想是面向接口编程。
在实际编程中,我们一般需要做到如下3点:
- 低层模块尽量都要有抽象类或接口,或者两者都有。
- 变量的声明类型尽量是抽象类或接口。
- 使用继承时遵循里氏替换原则。
接口隔离原则 (Interface Segregation Principle, ISP)
接口隔离原则的含义是:建立单一接口,不要建立庞大臃肿的接口,尽量细化接口,接口中的方法尽量少。
接口隔离原则与单一职责原则的区别,其一,单一职责原则注重的是职责,而接口隔离原则注重对接口依赖的隔离;其二,单一职责原则主要是约束类,其次才是接口和方法,它针对的是程序中的实现和细节,而接口隔离原则主要约束接口,主要针对抽象,针对程序整体框架的构建。
采用接口隔离原则对接口进行约束时,要注意以下几点:
- 接口尽量小,但是要有限度。对接口进行细化可以提高程序设计灵活性是不争的事实,但如果接口过小,则会造成接口数量过多,使设计复杂化,一定要适度。
- 为依赖接口的类定制服务,只暴露给调用的类它需要的方法,它不需要的方法则隐藏起来。只有专注地为一个模块提供定制服务,才能建立最小的依赖关系。
- 提高内聚,减少对外交互。使接口用最少的方法去完成最多的事情。
迪米特法则(最少知道原则)(Demeter Principle, DP)
定义:一个对象应该对其他对象保持最少的了解。
通俗的讲,就是一个类对自己依赖的类直到的越少越好。也就是说,对于被依赖的类,无论逻辑多么复杂,都尽量地将逻辑封装在类的内部,对外除了提供的public方法,不对外泄露任何信息。
将迪米特法则运用到系统设计时,要注意以下几点:
- 在类的划分上,应当尽量创建松耦合的类,类之间的耦合度越低,就越有利于复用,一个处在松耦合中的类一旦被修改,不会对关联的类造成太大波及;
- 在类的结构设计上,每一个类都应当尽量降低其成员变量和成员函数的访问权限;
- 在类的设计上,只要有可能,一个类型应当设计成不变类;
- 在对其他类的引用上,一个对象对其他对象的引用应当降到最低。
开闭原则(Open Close Principle, OCP)
定义:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情况下进行扩展。
开闭原则是面向对象设计中最基础的设计原则。
单一职责原则告诉我们实现类要职责单一;里氏替换原则告诉我们不要破坏继承体系;依赖倒置原则告诉我们要面向接口编程;接口隔离原则告诉我们在设计接口的时候要精简单一;迪米特法则告诉我们要降低耦合。而开闭原则是总纲,他告诉我们要对扩展开放,对修改关闭。