设计原则
面向对象的分析设计有很多原则,这些原则大多从思想层面给我们指出了面向对象分析设计的正确方向,是我们进行面向对象分析设计时应该尽力遵守的准则。而设计模式已经是针对某个场景下某些问题的某个解决方案,也是说这些设计原则是思想上的指导,而设计模式是实现的手段,因此设计模式也应该遵守这些原则,换句话说,设计模式就是设计原则的一些具体体现。如有疏漏与不足,恳请不吝赐教,非常感谢!
一、单一职责原则
单子职责原则SRP(Single Responsibility Principle) :一个类应该仅有一个引起它变化的原因。
这里变化的原因就是所说的 "职责" ,如果一个类有多个引起它变化的原因,说明这个类有多个职责,把多个职责耦合在一起了。可能一个职责的变化,会影响到其他职责的实现,甚至引起其他职责随着变化。单一职责看起来简单好理解,但是在实际开发中是最容易违反的,难点在于如何区分职责,哪些算职责,职责的粒度是多大,怎样细化职责?
二、开放关闭原则
开闭原则OCP(Open-Closed Principle):一个类应该对扩展开放,对修改关闭。
实现开闭原则的关键在于合理地抽象、分离出变化和不变化的部分,为变化的部分预留下可扩展的方式。比如:钩子方法或者是动态组合的对象等。一个系统完全做到遵守开闭原则几乎是不可能的,也没这必要。适度的抽象可以提到系统的灵活性,使其可扩展、可维护。不要过度地抽象,在需要改变的地方应用开闭原则,避免陷入过度设计。
三、里氏替换原则
里氏替换原则LSP(Liskov Substitution Principle):子类型必须能替换掉它们的父类型。
这是一种多态的使用,它可以避免在多态的应用中出现隐蔽的错误。例如:当一个类继承了另外一个类,子类就拥有了父类中的属性和操作,理论上子类型替换父类型不会引起程序出现错误。但是子类覆盖了父类的某些方法,或者子类修改了父类的某些属性值,原来使用父类型的程序可能出错,出错的原因是,在表面上看它调用的是父类的方法,实际上调用的是子类的方法,因为子类重写了继承的方法。
里氏替换原则是实现开闭原则的主要原则之一,开闭原则要求扩展开放,扩展的一个实现手段是继承,而里氏替换原则是保证子类能够正确替换父类,只有正确替换,才能实现扩展,否则扩展了也会出现错误。
四、依赖倒置原则
依赖倒置原则DIP(Dependence Inversion Principle):不要依赖于具体类。
做到依赖倒置典型的应该做到:
- 高层模块不应该依赖于底层模块,二者都应该依赖于抽象。
- 抽象不应该依赖于具体实现,具体应该依赖于抽象。
很多人觉得,层次化调用的时候,应该是高层次调用低层次所拥有的所有接口,这个一种误解。事实上,一般高层次模块包含对业务功能的处理和业务策略选择,应该被重用,是高层模块去影响底层的具体实现。因此这个底层的接口应该是由高层提出的,然后由底层实现的,也就是说底层的 接口的所有权 在高层模块,因此是一种所有权的倒置。
五、接口隔离原则
接口隔离原则ISP(Interface Segregation Princliple):接口不应该强迫客户依赖于他们不用的方法。
这个原则用来处理那些比较庞大的接口,这种接口通常会有较多的操作说明,涉及到很多职责,客户在使用这样的接口时候,通常会有很多他不需要的方法,这写方法对客户来说就是接口污染。
因此这样的接口需要被分离,应该按照不同的客户需求来分离成为针对用户的接口。分离的方式,除了直接进行代码分离之外,还可以使用委托来分离接口,通过多重继承。
六、最少知识原则
最少知识原则LKP(Least Knowledge Principle):只和你的朋友谈话。
这个原则用来指导我们在设计系统的时候,应该尽量减少对象之间的交互,对象只和自己的朋友谈话,也就是只和自己的朋友交互,从而松散类之间的耦合。通过松散耦合来降低类之间的相互依赖,这样修改系统的某一个部分的时候不会影响其他部分,从而使得系统具有更好的可维护性。
那些对象可以当作朋友呢
- 当前对象本身
- 通过方法的参数传递进来对象
- 当前对象所创建的对象
- 当前对象的实例变量所引用的对象
- 方法内所创建或实例化的对象
总之,最少知识原则要求我们的方法调用必须保持在一定界限范围之内,尽量减少对象的依赖关系
小结
本文主要整理了一下常见的设计原则,设计原则在为我们进行软件设计时提供了重要的指导思想,设计原则并不是固定的原则,而是一些有助于提高系统可扩展性、可维护性和灵活性的指导方针。设计模式则是这些原则在某些具体场景中的实际应用。