1.定义
1.一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。
对组建的功能扩展是开放的,对原有代码的修改是封闭的
是面向对象设计的核心,是最基础的一个原则,其他五种设计原则都是针对于开闭原则的实现方式和方法
2.作用
- 可复用性
- 可维护性
3.案例
以LOL 选英雄为例子,提供英雄英雄,符文,天赋三个属性,具体的实现类CommonRole
/**
* 角色
*/
public interface IRole {
//英雄
String getHero();
//符文
String getFuWen();
//天赋
String getGenius();
}
public class CommonRole implements IRole {
//英雄
private String hero;
//符文
private String fuWen;
//天赋
private String genius;
public CommonRole(String hero, String fuWen, String genius) {
this.hero = hero;
this.fuWen = fuWen;
this.genius = genius;
}
@Override
public String getHero() {
return hero;
}
@Override
public String getFuWen() {
return fuWen;
}
@Override
public String getGenius() {
return genius;
}
}
写一个Main函数打印其内容
public class Main {
public static void main(String[] args) {
List<IRole> role = new ArrayList<>();
role.add(new CommonRole("盖伦","全肉符文","全肉天赋"));
System.out.println("英雄:"+role.get(0).getHero());
System.out.println("符文:"+role.get(0).getFuWen());
System.out.println("天赋:"+role.get(0).getGenius());
}
}
打印结果如下:
英雄:盖伦
符文:全肉符文
天赋:全肉天赋
随着项目的发展,在选择角色的这个环节增加了皮肤这个选项,那么本着开闭原则不可能在原有的接口中增加皮肤这个选择,如果在原有的接口上增加,不仅要修改接口,实现类,业务逻辑也要发生变化,最好的方式是对组建功能进行扩展,修改如下:
public interface ISkinRole extends IRole{
//皮肤
String getSkin();
}
在原有基础上增加ISkin接口,对应的实现类Skin
public class SkinRole implements ISkinRole {
//英雄
private String hero;
//符文
private String fuWen;
//天赋
private String genius;
//皮肤
private String skin;
public SkinRole(String hero, String fuWen, String genius, String skin) {
this.hero = hero;
this.fuWen = fuWen;
this.genius = genius;
this.skin = skin;
}
@Override
public String getSkin() {
return skin;
}
@Override
public String getHero() {
return hero;
}
@Override
public String getFuWen() {
return fuWen;
}
@Override
public String getGenius() {
return genius;
}
}
在main函数中新增加一条数据
public static void main(String[] args) {
List<IRole> role = new ArrayList<>();
role.add(new CommonRole("盖伦","全肉符文","全肉天赋"));
role.add(new SkinRole("剑圣","攻击符文","攻击天赋","天人合一皮肤"));
System.out.println("英雄:"+role.get(0).getHero() +" 符文:"+role.get(0).getFuWen()+" 天赋:"+role.get(0).getGenius());
System.out.println("英雄:"+role.get(1).getHero() +" 符文:"+role.get(1).getFuWen()+" 天赋:"+role.get(1).getGenius());
}
打印结果如下:
英雄:盖伦 符文:全肉符文 天赋:全肉天赋
英雄:剑圣 符文:攻击符文 天赋:攻击天赋
OK!在没有修改其他业务就实现了对皮肤功能的扩展,完成了业务的变化。
4.总结
抽象层尽量保持稳定,一旦确定就不要修改,参数类型、引用对象尽量使用接口或者抽象类,而不是实现类。掌握并运用好设计模式,将轻松的适应不同的变化。