- 设计原则是思想上的指导
- 设计模式是实现上的手段
- 设计模式是设计原则的具体体现
- 在实际开发中,很少做到完全遵守,总是在有意无意的违反一些或者部分原则
- 设计是一种危险的平衡艺术A
单一职责原则(SRP)
Single Responsibility Principle
- 就一个类而言,应该仅有一个引起它变化的原因(职责)。
- 如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会削弱或者一直这个类完成其他职责的能力。这种耦合会导致脆弱的设计,当变化发生时,设计会遭受到意想不到的破坏。
- 难点在于如何区分职责、职责的粒度问题
- 软件设计真正要做的内容,就是发现职责并把那些职责相互分离。
- 如果你能够想到多于一个的动机去改变一个类,那么这个类就具有多于一个的职责,就应该考虑累的职责分离。
- 单一职责原则适用于接口、类,同事也适用于方法。
开放-封闭原则(OCP)
Open-Closed Principle
- 一个软件应当对扩展开放,对修改关闭。
- 需要考虑:怎样设计才能面对需求的改变却可以保持相对稳定,从而使得系统可以在第一个版本以后不断推出新的版本。
- 面对需求,对程序的改动通过增加新的代码进行的,而不是更改现有代码。
- ==合理地抽象、分离出变化与不变化的部分。==未变化的部分预留下可扩展的方式。eg:钩子方法或是动态组合对象。
- 要完全遵守开闭原则是不可能的,也没这个必要。适当的抽象可以提高系统的灵活性,使其可扩展、可维护;过度抽象,会大大增加系统的复杂程度。
- 钩子方法:是对于抽象方法或者接口中定义的方法的一个空实现。
里式代换原则(LSP)
Liskov Substitution Principle
- 子类型必须能够替换他们的基(父)类型。子类型可以以父类的身份出现。
- 前提:由于子类型的可替换性才使得使用父类型的模块在无需修改的情况下就可以扩展。
依赖倒转(置)原则DIP)
Dependence Inversion Principle
- 要依赖于抽象,不要依赖于具体
- 依赖倒转原则要求客户端依赖于抽象耦合。
-
- 抽象不应当依赖于具体实现;具体实现应当依赖于抽象;
-
- 高层模块不应当依赖于低层模块,二者都应该依赖于抽象。
-
- 要针对接口编程,不针对实现编程。
强内聚、松耦合
层次化调用的时候,应该是高层调用“底层所拥有的的就扣”,这是一典型的误解。
- 要针对接口编程,不针对实现编程。
- 一般高层包含对业务功能的处理和业务策略选择,应该被重用,是高层模块去影响底层的具体实现。
- 这个底层的接口应该是由高层提出的,然后由底层实现,即底层的接口的所在权在高层模块,是一种所有钱的倒置。
如何在项目中使用这一规则
- 每个类尽量都有接口或抽象类
- 变量的便面类型尽量是接口或者抽象类
- 任何类都不应该从具体类派生
- 结合里式代换原则使用
使用传统过程化程序设计所创建的依赖关系,策略依赖于细节,这是糟糕的,因为策略模式收到细节改变的影响。依赖倒置原则是细节和策略都依赖于抽象,抽象的稳定性决定了系统的稳定性。
迪米特法则(LOD)
迪米特法则(Law of Demeter)又叫最少知识原则(Least Knowledge Principle,LKP)
- 如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。
- 一个对象应当对其他对象有尽可能少的了解
每个软件单位对其他的单位都只有最少的只是,而且局限于哪些与本单位密切相关的软件单位。
- 迪米特法则其根本思想,是强调了类之间的松耦合。
- 类之间的耦合越弱,又有利于复用,一个处于弱耦合的类被修改,不会对有关系的类造成波及。
- 信息的隐藏促进了软件的复用。
合成/聚合复用原则
要尽量使用合成/聚合,而不是继承关系达到复用的目的。
合成/聚合原则就是在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分;新的对象通过向这些对象的委派达到复用已有功能的目的。
接口隔离原则
Interface Segregation Principle
- 使用多个专门的接口比使用单一的总接口要好。
从一个客户类的角度来讲:UI各类对另外一个类的依赖性应当是建立在最小借口上的。 - 过于臃肿的接口是对接口的污染。不应该强迫客户依赖于他们不用的方法。
实现方法:使用多重继承分离接口。
小结
- 单一职责原则
就一个类而言,应该仅有一个因其他变化的原因。 - 开放-封闭原则
一个软件实体应当对扩展开放,对修改关闭 - 里式代换原则
子类型必须能够替换他们的基(父)类型 - 依赖倒转(置)原则
要依赖于抽象,不要依赖于具体 - 接口隔离原则
使用多个专门的接口比使用单一的总接口总要好 - 合成/聚合复用原则
要尽量使用合成/聚合,而不是继承管子达到复用的目的 - 迪米特法则
一个软件实体应当尽可能少的与其他实体发生相互作用。