在面向对象编程领域中,开闭原则规定“软件中的对象(类,模块,函数等等)应该对于扩展是开放的,但是对于修改是封闭的”,这意味着一个实体是允许在不改变它的源代码的前提下变更它的行为。该特性在产品化的环境中是特别有价值的,在这种环境中,改变源代码需要代码审查,单元测试以及诸如此类的用以确保产品使用质量的过程。遵循这种原则的代码在扩展时并不发生改变,因此无需上述的过程。
开闭原则的命名被应用在两种方式上。这两种方式都使用了继承来解决明显的困境,但是它们的目的,技术以及结果是不同的。----WIKIPEDIA
个人对于开闭原则的理解:
开闭原则相当于一个纲领性质的原则,提倡类等应该在设计完成后通过扩展的方式适应新的业务需求,而不是通过修改的方式去适应新的需求,这样的设计更加灵活、稳定。之前的五大原则是开闭原则思想的具体实现的情况。
归纳总结:
1. 单一职责原则是从类的功能的角度去设计,将不同的职责分别归于不同的类中,这样使得设计更加清晰、易修改。
2. 里氏替换原则是从类的继承的角度去设计,强调父类被子类继承后,在父类出现的地方,可以替换为其子类,而且行为不会发生变化。
3. 依赖倒置原则是从类之间依赖关系的角度去设计,强调高层不依赖于低层,低层依赖于高层,减少实现细节的依赖。
4. 接口隔离原则是从接口的方法设计角度去思考,强调不能过度设计接口,尽量使得接口内的方法能充分的提供给其实现类需要的功能,不要过度设计导致方法的冗余,也不要设计不充分导致,实现类中有未能抽取的公共部分。
5. 迪米特法则或最少知识原则,从类与类之间耦合的角度去思考,降低耦合,减少不必要的耦合,不要跨越多层去调用方法,最佳的方式是只调用其朋友类的方法,之后行为由朋友类负责实施。
源代码我会同步放于GitHub上,需要的朋友可以进行关注下载:下载源代码
下面看这样一个例子:
理解对扩展开放,对修改关闭是什么意思。
直接上代码,类关系简单这里不再画类图
public interface Car { public String getCarName(); }
public class RealCar implements Car{ private String carName; public RealCar() { super(); } public RealCar(String carName) { super(); this.carName = carName; } @Override public String getCarName() { return carName; } }
private static List<RealCar> carList = new ArrayList<RealCar>(); static { carList.add(new RealCar("HongQI")); carList.add(new RealCar("BYD")); } public static void main(String[] args) { for (RealCar car : carList) { System.out.println(car.getCarName()); } }
假如需求变更了,需要可以查看颜色,怎么办?去修改Car接口?
NO!!不要去修改,因为你怎么知道他在别的地方有没有被用到过,一个小的项目中或许你说你知道,但是一个大项目里面,你和别人共同在做这一块东西,那就不确定了吧,那么这里按照开放关闭原则改下设计。
CarMore这个接口可以继承Car接口,那么这个接口也就拥有了Car接口中的方法了。
public interface CarMore extends Car{ public String getColor(); }
同样的,扩展的类继承原来实现Car接口的类RealCar,这样就完成了对新的业务需求的更改。原来的程序保持原来的状态。同时也减少了因为原来的类更改而造成的测试量增大的危险。
public class RealCarMoreInfo extends RealCar{ private String color; public RealCarMoreInfo() { super(); } public RealCarMoreInfo(String carName, String color) { super(carName); this.color = color; } public String getColor() { return color; } }