设计原则之:开闭原则

开闭原则:  一个软件个体,应该对扩展开放,对修改关闭。

 

Open - Closed Principle  (  OCP ) 

Software Entities should be open for extension, closed for modification. 

                      —— Bertrand Meyer.

 

这个定义有些high level,那么如何实现开闭原则?

它的核心意义是:“对可变性的封装”

 

啥叫“对可变性的封装”?首先要找到“可变性”。

 

例子1:一个UI系统,需要要显示一个圆,有时候也需要显示一个矩形,有时又要显示一个三角形。那么,此处“显示什么图形”就是一种“可变性”,找到这个“可变性”,就找到了要封装的对象。

 

例子2:一个排序系统,需要利用冒泡排序法来排序,有时又需要使用快速排序法来排序,有时又需要使用shell排序法……,在此处,使用什么算法进行排序,就是一种“可变性”,也即要封装的对象。

 

如何封装“可变性”?

 

很简单,一种“可变性”一定会有诸多种可变的形态(如同上述的各种排序算法,各种图形),这一系列的可变形态也必然有共性,要不然也不会归为同一种“可变性”。

那么,共性作为抽象的类或接口,而各种实际的可变的形态作为具体实现类。

参考:策略模式。

 

在实际的工作中,“开闭原则”一般设计过程,可能是先满足一种特性,然后考虑到这种特性会有变化,则把这种变化封装起来。

举例来说:上述例子2,最初拿到的需求可能只要求用冒泡排序来实现,可能直接一个方法一个类就搞定了。后来,需求发生了改动,要求再实现使用快速排序方法来实现,那么,这个时候,可能就会考虑,“下一次会不会再让我增加一种堆排序的方法呢?”。

接着,发现了一种“可变性”,即:使用什么排序算法来实现,是一种“可变性”,这时就需要将原有代码进行重构,使用开闭原则,将“可变性”进行封装。

 

将“可变性”封装是开-闭原则的核心。它有两个要点:

 

(1)单一性。 对每一种可变性,进行单独的封装,一般情况下,不要将多种可变性封装到一起。

    举例:如果有一个需求集合了上述例子1和2的功能,即根据图形的创建时间,对各种图形按多种排序算法进行排序。那么将“各种图形”与“各种排序算法”两个“可变性”单独进行封装。否则,代码的理解难度将会相当 的大。

    当然,如果一个软件系统中,有多个“可变性”之间有关联,则可参考桥梁模式

 

(2)有穷性。 对每一个发现的“可变性”进行封装,意味着,对可变性的封装是有穷的。

    “发现可变性”是设计者的行为,而且与需求强相关,比如,如果在例子2中,我们可以非常地确定只需要使用快速排序,其实排序方法根本不可能使用,而且客户也不会关心这些。那么,我们就没必要自己在那里“臆想”:既然写了快速排序,不如抽象一把,以便支持所有的排序算法吧,顺便可以让大家看看我的代码有多种牛B。

     有以上想法的,肯定是有追求的程序员。但是,Too Young Too Simple。不要试图封装“所有的”可变性。

 

     对”可变性“,发现了并确定后,才使用开-闭原则进行处理,而非要求设计者必须考虑得面面俱到。比如,一个画图软件,可以让用户画圆、画三角形、画矩形等等。那么,在设计时,只需要考虑”各种图形“这一可变性。可能有的人会考虑,用户还有男有女,有老有少,说不定有一天我们的系统根据用户的身份显示不同的风格给用户,所以我也要将”用户”这一可变性进行封装——这完全没有必要。

 

    过度的设计,对代码是一种污染。

 

你可能感兴趣的:(设计原则)