设计原则之开闭原则(Java)

本文介绍开闭原则,即软件实体应对拓展开放、对修改关闭。核心是用抽象构建框架,用实现扩展细节。通过课程打折需求变更的示例,说明开发中接口应保持稳定,可通过拓展而非修改来应对变化,还提及不同项目接口处理方式及开闭原则优缺点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

定义:一个软件实体如类,模块和函数应该对拓展开放,对修改关闭

所谓开闭实际上是对实际代码开发中的两个行为(拓展和修改)期望的原则。

在实际开发业务中,我们会针对业务的不同,需求的变更去修改我们的代码,貌似没办法做到不修改。

那么所谓的对修改关闭肯定是有对象选择的,比如底层的代码,比如功能性代码(最常见的就是一般架构师封装好的CRUD),像这些代码是我们不需要去对它修改的,当然像一些资深的程序员对业务建模时建好的业务底层代码也是不需要去修改的。

理解开闭原则的核心是:用抽象构建框架,用实现扩展细节

下面用一个简单的demo来演示什么场景下我们要考虑开闭原则

public interface ICourse {

    Integer getId();

    String getName();

    Double getPrice();
}
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;
    }

    public Integer getId() {
        return this.id;
    }

    public String getName() {
        return this.name;
    }

    public Double getPrice() {
        return this.price;
    }
}

上面用一个接口表示要开发的功能,用具体的实现类表示具体的要求,然后下面用main方法模拟客户端的请求。这个业务知识单纯的查出当前课程的相关信息

public class Test {
    public static void main(String[] args) {
        ICourse javaCourse = new JavaCourse(96, "java课程", 348d);
        System.out.println(javaCourse.getId() + "     " + javaCourse.getName() + "     " + javaCourse.getPrice());
    }
}

下面需求变更来了:

现在课程将开启打折活动,那么接下来,你打算如何修改你的业务代码?

撇开直接在客户端请求的时候把单纯的价格乘以折扣这种做法,恐怕你第一个想到的是直接在接口新增一个:获取折扣价的方法

你在接口新增了一个方法,那是不是所有实现该接口的类都要新增一个方法,如果类少那还可以忍忍,类多心态是不是得崩了,如果有的课程它是不参与打折活动的呢?如果是高于300块才参与打折呢?

这里强调一点:我们开发过程中接口是不应该经常变化的,且应该是稳定可靠的,所以我们应该往拓展的方向动脑子

当然有的人肯定会想,要不直接在JavaCourse这个类去修改getPrice方法,或者新增方法,个人建议还是不要的,你不能单纯只考虑眼前,你还得考虑以后,那么你可以为JavaCourse拓展出一个专门处理折扣的类,我们这里把它起名为JavaDiscountCourse,利用继承这一特性进行拓展

public class JavaDiscountCourse extends JavaCourse {
    public JavaDiscountCourse(Integer id, String name, Double price) {
        super(id, name, price);
    }

    public Double getOriginPrice() {
        return super.getPrice();
    }

    @Override
    public Double getPrice() {
        return super.getPrice()*0.8;
    }
}

于是所有有关于折扣的业务可以在这个类上去处理,客户端的模拟请求则依然可以利用多态的特性去完成这个业务

public class Test {

    public static void main(String[] args) {
        ICourse javaCourse = new JavaDiscountCourse(96, "java课程", 348d);
        System.out.println(javaCourse.getId() + "     " + javaCourse.getName() + "     " + javaCourse.getPrice());
    }
}

关于业务代码如何开发,我这里不得不谈几点,如果是新项目从0开始的,业务的变更很频繁的,那么接口一定会经常变化,如果是接手旧项目,接口是尽量能不动就不动的,因为一旦你更改这种底层的代码,势必会引入风险,保不准会引起bug

最后稍微小结一下开闭原则的优缺点:

优点:提高系统的可复用性和可维护性
缺点:容易引起类爆炸(类特别多)

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值