写点什么

重新学习面向对象设计之开放 - 封闭原则

发布于: 2020 年 10 月 15 日

作为一名程序猿,每个人心中有一个小窃喜:自己的代码从产品的第一版本开始永存,也已有一点小愤怒:自己的代码经常被重构掉,还经常被说道,这代码写的真差。作为一位15+的老码农,也曾经历各种代码情绪,也会因为自己的代码被认可而开心,也会因自己的代码造成损失而懊恼。面向对象设计原则之开放-封闭原则

正是解决这个问题的。

一、什么是开放-封闭原则

定义:开放-封闭原则,Open Closed Principle,OCP,Software entities (classes, modules, functions) should be open for extension but closed for modification. 软件中的对象(类,模块,函数等等)应该对于扩展是开放的,但是对于修改是封闭的。

OCP原则设计出的模块具有两个主要的特征:

  • 对于扩展是开放的(Open for extension)。模块对扩展开放,就意味着需求变化时,可以对模块扩展,使其具有满足那些改变的新行为。换句话说,模块通过扩展的方式去应对需求的变化。

  • 对于更改是封闭的(Closed for modification)。模块对修改关闭,表示当需求变化时,关闭对模块源代码的修改,当然这里的“关闭”应该是尽可能不修改的意思,也就是说,应该尽量在不修改源代码的基础上面扩展组件。

这两个特征好像是互相矛盾的。扩展模块行为的通常方式就是修改该模块的源代码。不允许新修改的模块常常都被认为是具有固定的行为。

二、如何实现OCP

怎样可能在不改动模块源码的情况下去更改它的行为呢?怎么才能在无需对模块进行改动的情况下就改变它的功能呢?关键是抽象。

在Java、C++等面向对象语言中,可以创建出固定却能描述一组任意个可能行为的抽象体,这个抽象体就是抽象基类,而这一组任意个可能的行为则表现为可能的派生类。模块可以操作一个抽象体。由于模块依赖于一个固定的抽象体,所以它对于更改可以是关闭的,同时,通过从这个抽象体派生,也可以扩展此模块的行为。

上述这段话来自《敏捷软件开发》,听起来还有有些抽象难以理解,下面我们通过一个例子来了解一下。

2.1 不遵守OCP





图1 不开放又不封闭的Client

图1中展示了一个简单的不遵循OCP的设计。Client类和Server类都是具体类。Client类使用Server类,如果我们希望Client对象调用另外一个不同的Server对象,那么就必须要把Client类中使用Server类的地方更改为新的Server类。

2.2 遵循OCP的例子





图2 遵循OCP的Client

图2是针对图1问题的改进,采用了策略模式,增加了ServerInterface接口类,client类调用ServerInterface接口来,不关心具体是哪个Server类对象。当需要调用另外一个Server类对象时,只要再实现一个ServerInterface的Server类就可以了,无需对Client类做任何修改。

2.3 再改进

是不是以上设计100%遵循OCP了?这个不一定,需要看具体的需求变化,更确切的来说,很难有100%的OCP。这么说可能会更糊涂了,到底怎么算是遵循OCP了呢?到底怎么做才算OK呢?这是需要需求、成本、质量进行综合评估和衡量。但有些是可以做的。

1、预测变化

既然不可能完全封闭,那么就必须有策略地对待这个问题,也就是说,设计人员必须对于他设计的模块应该对哪种变化封闭做出选择,必须先猜测出最有可能给发生的变化种类,然后构造抽象来隔离那些变化。

这需要设计人员具备 一些从经验中获得的预测能力。有经验的设计人员希望自己对用户和应用领域很了解, 能够以此来判断各种变化的可能性,然后他可以让设计对于最有可能发生的变化遵循OCP原则。

要做到这样是非常不容易的,而且也需要付出高昂的代价,我们需要设定一个度,防止过于复杂以及过高的成本。

架构师思维:预测最可能变化的地方,采用合适的设计模式,至少能够满足当前需求和未来一定版本数。

2、允许错误

当无法预测变化时,我们可以运行一次错误。如果不发生需求变化,那我们就不用过多的设计,满足当前需求的设计遵循OCP就可以。

三、总结

总的来说,OCP是面向对象设计的核心之一,遵循OCP原则可以带来面向对象计生户所声称的好处(灵活性、可重用性会和可维护性)。但并不是说需要随意的进行抽象,这还会带来另外的一些问题。

正确的做法是,开发人员应该仅仅对程序中呈现出频繁变化的那些部分作出抽象。

拒绝不成熟的抽象和抽象本身一样重要。



发布于: 2020 年 10 月 15 日阅读数: 35
用户头像

IT老兵 2018.04.25 加入

还未添加个人简介

评论

发布
暂无评论
重新学习面向对象设计之开放-封闭原则