# 设计模式的六大设计原则 #
## 1.单一职责原则(Single Responsibility Principle,SRP) ##
**1.1 单一职责的原则是:应该有且仅有一个原因引起类的变更。**<br>
单一职责原则提出了一个编写程序的标准,用”职责“或”变化原因“来衡量接口和类设计的是否优良,但是”职责“或”变化原因“是因项目和环境而异的。<br>
**1.2 单一职责的好处**<br>
1. 类的复杂度降低,实现什么职责都有清晰明确的定义;<br>
2. 类的可读性提高;<br>
3. 可维护性提高;<br>
4. 变更引起的风险降低。<br>
##2.里氏替换原则(Liskov Substitution Principle,LSP) ##
**2.1 使用继承的坏处:**<br>
1. 继承是侵入性的,子类必须拥有父类的所有属性和方法;<br>
2. 继承降低了代码的灵活性;<br>
3. 增强了代码的耦合性,基类的修改必修考虑子类的变化。<br>
**2.2 里氏替换原则:所有引用基类的地方必须能透明的使用其子类对象。**<br>
里氏替换原则位继承定义了良好的规范:<br>
1. 子类必须完全实现父类的方法,在类中使用其他类时必须使用父类或者接口,如果子类不能完整的实现父类的方法,或者父类的某些方法在子类中已经发生”畸变“,则建议断开继承关系,采用依赖、聚集、组合等关系代替继承。<br>
2. 子类可以有自己的方法和属性。有子类出现的地方父类未必可以出现。<br>
3. 覆盖或者实现父类的方法是输入的参数可以被放大。子类中方法的前置条件必须与超类中被覆写的方法的前置条件相同或者更为宽松。<br>
4. 覆写或实现基类的方法时输出结果可以被缩小。
## 3.依赖倒置原则(Dependence Inversion Principle,DIP) ##
**3.1 依赖倒置在java语言中的体现:**<br>
1. 模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过抽象或者接口实现的;<br>
2. 接口或抽象类不依赖与实现类;<br>
3. 实现类依赖接口或抽象类。<br>
**3.2 对象的依赖关系有三种方式进行传递:**<br>
1. 通过构造函数来传递依赖对象(将依赖对象作为构造函数的参数传递);<br>
2. setter方法 传递依赖对象;<br>
3. 通过接口声明依赖对象,在接口的方法中声明依赖对象。<br>
**3.3 使用依赖倒置应该遵循的规则:**<br>
1. 每个类尽量都有接口或者抽象类,或者两者都有;<br>
2. 变量的表面类型尽量使接口或者抽象类;<br>
3. 任何类都不应该从具体类诞生;<br>
4. 尽量不要覆写基类方法;<br>
5. 结合里氏替换原则使用。<br>
## 4.接口隔离原则 ##
**接口尽量细化,同时接口中的方法尽量少。**<br>
接口隔离原则对接口进行规范约束,主要有以下4方面的含义:<br>
1. 接口尽量小,但是根据接口隔离原则分拆接口时,首先必须满足单一职责原则;<br>
2. 接口要高内聚,提高接口、类、模块的的处理能力,减小与外界的交互;<br>
3. 定制服务,有耦合就要有相互访问的接口;<br>
4. 接口的设计是有限度的。
## 5.迪米特法则(最少只是原则,Least Knowledge Principle,LKP) ##
**5.1 迪米特法则对类的低耦合提出了要求,有以下4层含义:**<br>
1. 只和朋友交流;<br>
2. 朋友之间也是有距离的;<br>
3. 如果一个方法放在本类中,既不增加类间的关系,也不对本类产生负面影响,就放置在本累中;<br>
4. 谨慎使用Serializable.<br>
## 6.开闭原则 ##
**一个软件实体如类、方法、模块应该对扩展开放,对修改关闭。**<br>
开闭原则在实际工作中的使用:<br>
1. 抽象约束:第一,通过接口或者抽象类约束扩展,对扩展进行边界限定,不允许出现接口或抽象类中不存在的方法;第二,参数和引用对象尽量使用抽象类和接口,不要使用具体类;第三,抽象层尽量保持稳定,一旦确定就不许在修改。<br>
2. 尽量使用元数据来控制程序的行为,减小重复开发。<br>
3. 制定项目章程。<br>
4. 封装变化:第一,将相同的变化封装到一个抽象类或者接口中;第二,将不同的变化封装到不同的接口或者抽象类中,不应该有两个不同的变化出现在同一个接口或者抽象类中。<br/>
**参考文献:**<br/>
《设计模式之禅》,秦小波
## 1.单一职责原则(Single Responsibility Principle,SRP) ##
**1.1 单一职责的原则是:应该有且仅有一个原因引起类的变更。**<br>
单一职责原则提出了一个编写程序的标准,用”职责“或”变化原因“来衡量接口和类设计的是否优良,但是”职责“或”变化原因“是因项目和环境而异的。<br>
**1.2 单一职责的好处**<br>
1. 类的复杂度降低,实现什么职责都有清晰明确的定义;<br>
2. 类的可读性提高;<br>
3. 可维护性提高;<br>
4. 变更引起的风险降低。<br>
##2.里氏替换原则(Liskov Substitution Principle,LSP) ##
**2.1 使用继承的坏处:**<br>
1. 继承是侵入性的,子类必须拥有父类的所有属性和方法;<br>
2. 继承降低了代码的灵活性;<br>
3. 增强了代码的耦合性,基类的修改必修考虑子类的变化。<br>
**2.2 里氏替换原则:所有引用基类的地方必须能透明的使用其子类对象。**<br>
里氏替换原则位继承定义了良好的规范:<br>
1. 子类必须完全实现父类的方法,在类中使用其他类时必须使用父类或者接口,如果子类不能完整的实现父类的方法,或者父类的某些方法在子类中已经发生”畸变“,则建议断开继承关系,采用依赖、聚集、组合等关系代替继承。<br>
2. 子类可以有自己的方法和属性。有子类出现的地方父类未必可以出现。<br>
3. 覆盖或者实现父类的方法是输入的参数可以被放大。子类中方法的前置条件必须与超类中被覆写的方法的前置条件相同或者更为宽松。<br>
4. 覆写或实现基类的方法时输出结果可以被缩小。
## 3.依赖倒置原则(Dependence Inversion Principle,DIP) ##
**3.1 依赖倒置在java语言中的体现:**<br>
1. 模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过抽象或者接口实现的;<br>
2. 接口或抽象类不依赖与实现类;<br>
3. 实现类依赖接口或抽象类。<br>
**3.2 对象的依赖关系有三种方式进行传递:**<br>
1. 通过构造函数来传递依赖对象(将依赖对象作为构造函数的参数传递);<br>
2. setter方法 传递依赖对象;<br>
3. 通过接口声明依赖对象,在接口的方法中声明依赖对象。<br>
**3.3 使用依赖倒置应该遵循的规则:**<br>
1. 每个类尽量都有接口或者抽象类,或者两者都有;<br>
2. 变量的表面类型尽量使接口或者抽象类;<br>
3. 任何类都不应该从具体类诞生;<br>
4. 尽量不要覆写基类方法;<br>
5. 结合里氏替换原则使用。<br>
## 4.接口隔离原则 ##
**接口尽量细化,同时接口中的方法尽量少。**<br>
接口隔离原则对接口进行规范约束,主要有以下4方面的含义:<br>
1. 接口尽量小,但是根据接口隔离原则分拆接口时,首先必须满足单一职责原则;<br>
2. 接口要高内聚,提高接口、类、模块的的处理能力,减小与外界的交互;<br>
3. 定制服务,有耦合就要有相互访问的接口;<br>
4. 接口的设计是有限度的。
## 5.迪米特法则(最少只是原则,Least Knowledge Principle,LKP) ##
**5.1 迪米特法则对类的低耦合提出了要求,有以下4层含义:**<br>
1. 只和朋友交流;<br>
2. 朋友之间也是有距离的;<br>
3. 如果一个方法放在本类中,既不增加类间的关系,也不对本类产生负面影响,就放置在本累中;<br>
4. 谨慎使用Serializable.<br>
## 6.开闭原则 ##
**一个软件实体如类、方法、模块应该对扩展开放,对修改关闭。**<br>
开闭原则在实际工作中的使用:<br>
1. 抽象约束:第一,通过接口或者抽象类约束扩展,对扩展进行边界限定,不允许出现接口或抽象类中不存在的方法;第二,参数和引用对象尽量使用抽象类和接口,不要使用具体类;第三,抽象层尽量保持稳定,一旦确定就不许在修改。<br>
2. 尽量使用元数据来控制程序的行为,减小重复开发。<br>
3. 制定项目章程。<br>
4. 封装变化:第一,将相同的变化封装到一个抽象类或者接口中;第二,将不同的变化封装到不同的接口或者抽象类中,不应该有两个不同的变化出现在同一个接口或者抽象类中。<br/>
**参考文献:**<br/>
《设计模式之禅》,秦小波