0103_开闭原则

定义:软件实体(类、模块、函数等)应该对扩展开放,对修改关闭

场景

这里还上一篇【单一职责原则】中人类对象为例,人类属性有年龄、名称,动作有吃饭、行走、唱歌、跳舞、飞行等。现在需要增加跑步、跳远等运动员具备的技能。

反例


/**
 * 人类类
 * 
 */
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类,可能会影响其它引用类的逻辑。

正例

ArthlethHuman

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() + "在跳远");
    }
}

总结

  1. 稳定与变化的分离
  • 将稳定不变的基础属性(年龄、姓名)和核心行为(吃饭、行走)封装在BaseHuman
  • 将可能变化的扩展行为(艺术、运动、超能力)分离到独立子类
  1. 扩展而非修改
  • 新增运动功能时创建AthleteHuman类而非修改BaseHuman
  • 每种特殊能力都有专属类实现,互不干扰

本方案通过经典的继承体系,既满足了开闭原则的要求,又保持了代码的简单直观,特别适合中等复杂度的业务场景。当系统行为维度超过5个时,建议升级为接口组合模式以获得更大灵活性。

posted @ 2025-08-16 21:57  庞去广  阅读(9)  评论(0)    收藏  举报