EasyText, EasyLicense 的作者, https://github.com/EasyHelper Good Good Study,Day Day Up.

 

Clean-Code: 面向过程 PK 面向对象

面向过程:

假设有两个类Square(正方形),Rectangle(长方形) 。代码如下:

image 

 

如果有一个类Geometry需要计算图形的面积:

image

假设现在要添加一个Circle(圆形),并且同样需要计算Circle的面积。那么需要做哪些修改:

1:需要添加Circle类,代码如下:

image

2:因为需要计算Circle的面积,所以Geometry类需要修改

 

image

可以看到增加了sharp is Circle 的判断。

 

假设现在Geometry类不仅仅需要计算面积,还需要计算sharp的周长。

那么Geometry的代码大致如下:

image

可以发现,SquareRectangleCircle这三个类不需要做任何更改。

也就是说当需要添加函数的时候,数据结构不会受到影响。

 

 

 

面向对象:

如果使用面向对象的角度来思考这个问题,那么该怎么处理呢?

基本上有 if else,switch的地方就可以考虑使用策略模式。

 

首先可以创建抽象类Shape,或者是接口IShape

image

当然,在这里随便使用哪一个都可以,因为除了计算面积之外,目前不需要继承字段,属性,所以我选择了接口

 

Area的名字是面积,不过并没有体现出获取面积这个动作,所以我决定将Area重命名为GetArea或者是CalculateArea

代码如下:

image 

 

 

接着创建实现类,Square,Rectangle

image 

 

Geometry类的实现就比较简单了

image

同样,如果需要添加一个Circle,然后计算Circle的面积。那么该如何做呢?

 

很简单,添加一个Circle类就可以了,Geometry不需要任何变化。

image

也就是说添加数据结构的同时,方法不受影响。

 

如果现在要添加一个计算周长的方法呢?

首先IShape接口要增加GetPerimeter 方法。

image

如果现在编译的话,会得到下面的结果:

image

无法通过编译有2点好处:

  1. 修改了接口会导致无法通过编译,这是面向过程无法提供的,比如在面向对象的方案中Geometry中的GetPerimeter方法如果忘记了添加Circle的判断,那么编译一样可以通过。
  2. GetPerimeter方法由类自行管理,复杂度大大下降,代码结构更加清晰。

 

Square为例:代码如下:

image

如果这时候编译,可以发现,可以编译通过。

所以面向对象的特点是修改数据结构的同时,不影响方法,也就是说添加一个类,不会对原系统的方法有影响。

 

当然在这里Geometry 需要添加GetPerimeter方法:

image

posted @ 2011-09-20 06:27  LoveJenny  阅读(1736)  评论(6编辑  收藏  举报
EasyText, EasyLicense 的作者, https://github.com/EasyHelper Good Good Study,Day Day Up.