1.封装变化
找出应用中可能需要变化之处,把它独立出来,不要与那些不需要变化的代码混在一起。换句话说,如果每次需求一更新,都会使某方面的代码发生变化,那么你就可以确定,这部分的代码需要被抽离,和其他稳定的代码有所区别。这个原则,几乎是每个设计模式背后的精神所在。
2.少用继承,多用组合
使用组合建立系统具有很大的弹性,不仅可以将算法族封装成类,更可以在运行时动态地改变行为,只要组合的行为对象符合正确的接口标准即可。组合被使用在很多“设计模式”中,比如策略模式。
3.针对接口编程,不针对实现编程
“针对接口编程”真正的意思是“针对超类型编程”。针对接口编程,关键在意多态。利用多态,程序可以针对超类型编程,执行时会根据实际的状况执行真正的行为,不会被绑死在超类型的行为上。“针对超类型编程”这句话,可以更明确的理解为“变量的声明类型应该是超类型,通常是一个抽象类或者是一个接口”,这也意味着,声明类时不用理会以后执行时的真正对象类型。比如下面这个例子:
//针对实现编程
Dog d = new Dog();
d.bark();
//针对接口编程
Animation a = new Dog();
a.makeSound();
//更好的实现
a = getAnimation();
a.makeSound();
4.为交互对象之间的松耦合设计而努力
所谓松耦合,即是指两者只通过简单的一套接口进行交互,而与具体的类型无关。有点类似于“针对接口编程,不针对过程编程”。最好的例子是观察者模式,只要目标与观察者之间遵循一套Observer接口,那么运行时我们可以用任意层次的新观察者取代现有的观察者,也可以用任意层次的木匾取代现有的目标,我们不需要为了兼容新类型而修改代码。改变他们之间的接口仍然被遵守,我们就可以自由地改变他们,松耦合的设计能够让我们建立有弹性的系统。
5.类应该为扩展开发,对修改关闭
这个原则的目标是允许一个类在不修改现有代码的情况下可以容易扩展,对修改关闭即指不能修改类本身,对扩展开发即指类本身的功能又很容易被客户扩展。其中装饰者模式就很好的体现了这个准则。
当然我们不必在代码的每个设计都使用此准则,因为开放-关闭原则通常会引入新的抽象层次,增加代码的复杂度,我们只需要集中在设计最有可能改变的地方,然后应用开发-关闭原则。所以实际设计中,我们要小心选择需要被扩展的代码部分。