面向对象设计原则之开-闭原则

目录

定义

开闭原则(Open Closed Principle, OCP)由勃兰特·梅耶(Bertrand Meyer)提出,他在 1988 年的著作《面向对象软件构造》(Object Oriented Software Construction)中提出:软件实体应当对扩展开放,对修改关闭(Software entities should be open for extension,but closed for modification),这就是开闭原则的经典定义。

这里的软件实体包括以下几个部分:

  1. 项目中划分出的模块
  2. 类与接口
  3. 方法

开闭原则的含义是:当应用的需求改变时,在不修改软件实体的源代码或者二进制代码的前提下,可以扩展模块的功能,使其满足新的需求。

作用

开闭原则是面向对象程序设计的终极目标,它使软件实体拥有一定的适应性和灵活性,但同时具备稳定性和延续性。具体作用如下:

  1. . 对软件测试的影响:如果软件遵循开闭原则,软件测试时只需要对扩展的代码进行测试就可以了,因为原有的逻辑未修改,原有的测试代码逻辑也仍然能够正常运行。
  2. 提高代码可复用性:粒度越小,可复用的可能性就越大;在面向对象的程序设计中,根据原子和抽象编程可以提高代码的可复用性。
  3. 提高软件可维护性:遵循开闭原则的软件,其稳定性和延续性强,从而易于扩展和维护。

实现方法

通过"抽象约束、封装变化"来实现开闭原则,即通过接口或者抽象类为软件实体定义一个相对稳定的抽象层,而将相同的可变因素封装在具体的实现类中;用抽象构建框架,用实现类实现具体细节。

代码示例

java 复制代码
package will.tools.design;
 
/**
 * 定义个课程接口,定义公共行为方法
 * getName() 课程名称
 * getPrice() 课程价格
 */
public interface ICourse {
    Integer getId();
 
    String getName();
 
    Double getPrice();
}

package will.tools.design;
 
public class JavaCourse implements ICourse {
 
    private Integer id;
 
    private String name;
 
    private Double price;
 
    public JavaCourse(Integer id, String name, Double price) {
        this.id = id;
        this.name = name;
        this.price = price;
    }
 
    @Override
    public Integer getId() {
        return id;
    }
 
    @Override
    public String getName() {
        return name;
    }
 
    @Override
    public Double getPrice() {
        return price;
    }
 
    @Override
    public String toString() {
        return "课程ID:" + getId() +
                "\n课程名称:" + getName() +
                "\n课程价格:" + getPrice();
    }
}

定义课程接口ICourse,定义公共方法,获取课程名称、价格等;实现Java课程类JavaCourse,实例化具体课程对象;当需求发生变化,如Java课程价格发生变化(8折)时,我们可以在Java实现类中修改,如下图:

写一个main方法测试类,初始化一个java课程并输出

java 复制代码
package will.tools.design;
 
public class CourseTest {
    public static void main(String[] args){
    
        ICourse course = new JavaCourse(1,"java",100d);
        System.out.println(course.toString());
    }
}

输出结果如下

课程ID:1

课程名称:java

课程价格:80.0

但此时,其实已经违反了开闭原则,因为直接对业务需求进行了修改。即每次使用不同的折扣时,都需要修改一次JavaCourse类频繁修改原有的逻辑,在复杂业务中非常容易出现问题。这时,我们可以对修改关闭,即原JavaCourse中不要修改,而是采用扩展的方式,通过继承类,实现需求细节的修改,让我们的代码风险可控。实现如下:

java 复制代码
package will.tools.design;
 
public class JavaDiscountCourse extends JavaCourse {
    public JavaDiscountCourse(Integer id, String name, Double price) {
        super(id, name, price);
    }
 
    public Double getDiscountPrice() {
        return super.getPrice() * 0.8;
    }
 
    @Override
    public String toString() {
        return "课程ID:" + getId() +
                "\n课程名称:" + getName() +
                "\n课程原价:" + getPrice() +
                "\n课程折扣价:" + getDiscountPrice();
    }
}

写一个main方法测试类,初始化一个java课程并输出

java 复制代码
package will.tools.design;
 
public class CourseTest {
    public static void main(String[] args){
    
        ICourse course2 = new JavaDiscountCourse(1,"java",100d);
        System.out.println(course2.toString());
    }
}

结果如下:

课程ID:1

课程名称:java

课程原价:100.0

课程折扣价:80.0

相关推荐
蓝桉~MLGT4 天前
spring6合集——spring概述以及OCP、DIP、IOC原则
spring·依赖倒置原则·开闭原则
frank00600711 个月前
戴尔 17G 服务器 E610 OCP千兆网卡驱动安装
服务器·网络·开闭原则
进击的CJR1 个月前
MySQL 8.0 OCP 英文题库解析(十八)
android·mysql·开闭原则
进击的CJR1 个月前
MySQL 8.0 OCP 英文题库解析(十四)
android·mysql·开闭原则
进击的CJR1 个月前
MySQL 8.0 OCP 英文题库解析(十五)
数据库·mysql·开闭原则
进击的CJR1 个月前
MySQL 8.0 OCP 英文题库解析(十九)
数据库·mysql·开闭原则
进击的CJR1 个月前
MySQL 8.0 OCP 英文题库解析(十)
mysql·adb·开闭原则
博睿谷IT99_1 个月前
Oracle OCP与MySQL OCP认证如何选?
mysql·oracle·开闭原则
进击的CJR1 个月前
MySQL 8.0 OCP 英文题库解析(十一)
mysql·adb·开闭原则
小哈里1 个月前
【DBA】MySQL经典250题,改自OCP英文题库中文版(2025完整版)
数据库·mysql·dba·开闭原则·ocp