定义:软件实体(类、模块、函数等)应该对扩展开放,对修改关闭
场景
这里还上一篇【单一职责原则】中人类对象为例,人类属性有年龄、名称,动作有吃饭、行走、唱歌、跳舞、飞行等。现在需要增加跑步、跳远等运动员具备的技能。
反例
/*** 人类类* */
public class Human {// 年龄属性private int age;// 姓名属性private String name;/*** 构造方法* @param age 年龄* @param name 姓名*/public Human(int age, String name) {this.age = age;this.name = name;}/*** 吃饭方法 - 基本生存行为*/public void eat() {System.out.println("人类在吃饭");}/*** 行走方法 - 基本移动行为*/public void walk() {System.out.println("人类在行走");}/*** 唱歌方法 - 艺术家行为*/public void sing() {System.out.println("人类在唱歌");}/*** 跳舞方法 - 艺术家行为*/public void dance() {System.out.println("人类在跳舞");}/*** 跑步方法 - 运动员*/public void run() {System.out.println(this.name + "在跑步");}/*** 跳远方法 - 运动员*/public void jump() {System.out.println(this.name + "在跳远");}/*** 飞行方法 - 特殊能力行为* 注意:这个方法的存在说明了该类职责过多,因为不是所有人类都能飞行* 应该将特殊能力提取到子类或接口中实现*/public void fly() {if ("超人".equals(this.name)) {System.out.println(this.name + "正在飞行");} else {System.out.println("只有超人才能飞行");}}
}
在反例中,Human类承担了过多的职责,现在需要增加跑步、跳远等动作,需要修改Human类,可能会影响其它引用类的逻辑。
正例
BaseHuman类
- 职责:只处理人类基本属性和基本生存行为
- 稳定性高:这些是所有人共有的基本特征和行为
- 易于扩展:可作为其他人类类型的基类
public class BaseHuman {// 年龄属性private int age;// 姓名属性private String name;public BaseHuman(int age, String name) {this.age = age;this.name = name;}/*** 获取姓名* @return 姓名*/public String getName() {return name;}/*** 吃饭方法*/public void eat() {System.out.println(getName() + "在吃饭");}/*** 行走方法*/public void walk() {System.out.println(getName() + "在行走");}
}
SuperHuman类
- 职责:专门处理超人的特殊能力
- 隔离变化:特殊能力的修改不会影响普通人类
- 清晰性:明确表示这是特殊能力,不是普通人类行为
public class SuperHuman extends BaseHuman {public SuperHuman(int age, String name) {super(age, name);}/*** 飞行方法*/public void fly() {System.out.println(getName() + "正在飞行");}
}
ArtistHuman类
- 职责:专门处理艺术相关的行为
- 遵循开闭原则:可以独立修改艺术行为而不影响其他类
- 可扩展性:可轻松添加新的艺术行为方法
public class ArtistHuman extends BaseHuman {public ArtistHuman(int age, String name) {super(age, name);}/*** 唱歌方法*/public void sing() {System.out.println(getName() + "在唱歌");}/*** 跳舞方法*/public void dance() {System.out.println(getName() + "在跳舞");}
}
AthleteHuman类
- 职责:处理运动员特有的行为
- 遵循开闭原则:可以独立修改运动员行为而不影响其他类
- 可扩展性:可轻松添加新的运动员行为方法
public class AthleteHuman extends BaseHuman {public AthleteHuman(int age, String name) {super(age, name);}/*** 跑步方法*/public void run() {System.out.println(getName() + "在跑步");}/*** 跳远方法*/public void jump() {System.out.println(getName() + "在跳远");}
}
总结
- 稳定与变化的分离
- 将稳定不变的基础属性(年龄、姓名)和核心行为(吃饭、行走)封装在BaseHuman
- 将可能变化的扩展行为(艺术、运动、超能力)分离到独立子类
- 扩展而非修改
- 新增运动功能时创建AthleteHuman类而非修改BaseHuman
- 每种特殊能力都有专属类实现,互不干扰
本方案通过经典的继承体系,既满足了开闭原则的要求,又保持了代码的简单直观,特别适合中等复杂度的业务场景。当系统行为维度超过5个时,建议升级为接口组合模式以获得更大灵活性。
