开闭原则(OCP)

开闭原则是面向对象的可复用设计的第一块基石,它是最重要的面向对象设计原则。开闭原则定义为:一个软件实体应当对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情况下进行扩展。软件实体从不同的粒度可以理解为模块、类、方法或者属性。

为什么要有开闭原则

任何系统都会面临着一个重要的问题,需求会随着时间而进行迭代的。如果系统功能设计的符合开闭原则的话,那么在进行需求迭代的时候可以很方便的进行扩展,而无需对现有的逻辑代码进行修改,或者是对现有代码的修改尽可能的小。随着软件规模的增长,寿命会越来越长,软件的维护成本也会越来越高,系统的设计满足开闭原则也显得越来越重要了。

如何理解开闭原则

添加一个新的功能,应该是通过在已有的代码基础上进行扩展(新增模块、类、方法或者属性等),而非是修改现有的代码(修改模块、类、方法或者属性等)。但是有两点需要注意,第一点:开闭原则并不是说完全不能修改现有的代码,而是要求以最小修改代价来完成新功能的开发。第二点:在不同的粒度下对扩展和修改的认识不同,在类维度的视角下,修改该类中的代码属于修改,但是以该类中的方法为维度的视角下可能又被定义为扩展,所以扩展和修改并不是绝对的。

如何做到开闭原则

我们要时刻具备扩展意识、抽象意识、封装意识。抽象化是对软件进行开闭原则设计的关键,在不同编程语言中中可以为系统定义一个稳定的抽象层,将不同的实现放到不同的实现层中。在Java中可以通过抽象类、接口等机制来定义系统的抽象层,再通过具体类来实现扩展。如果需要进行修改,可以对具体的实现类进行修改,而无需对抽象层进行改动,以此实现开闭原则。

我们也可以在写代码的时候多花一点时间想想,这段代码在未来可能有什么改动,事先留好扩展点,现在可以怎么设计代码结构好应对未来的需求可以直接进行扩展而不进行修改代码。

继续用一个简单的例子来解释开闭原则。

在ShowCar类的displayCar()方法中有着如下代码段:

......
if (type.equals("bmw")) {
BMWCar bmwCar = new BMWCar();
bmwCar.displayCar();
}
else if (type.equals("audi")) {
AUDICar audiCar = new AUDICar();
audiCar.displayCar();
}
......

在该代码段中,如果需要在增加一个新的车品牌,则需要修改ShowCar类的displayCar()方法的源代码,增加新的判断逻辑,违反了开闭原则。

现对该系统进行重构,使之符合开闭原则。

在本例中,可以通过抽象化的方式对系统进行重构,已达到增加新的车品牌时无需进行修改源代码,满足开闭原则。具体方法如下:

(1)增加一个抽象类AbstractCar。将各种车品牌类作为其子类。

(2)ShowCar类对抽象car类进行操作,由客户端决定使用那种具体car类。

重构后的结构如图所示:

在上图中,我们引入了抽象图表类AbstractCar,且ShowCar针对抽象car类进行编程,并通过setCar()方法由客户端来设置实例化的具体car对象,在ShowCar的displayCar()方法中调用car对象的displayCar()方法显示car。如果需要增加一种新的car,只需要将新增品牌car也作为AbstractCar的子类,在客户端向ShowCar中注入一个改实例对象即可,无须修改现有类库的源代码。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值