• CleanCode: 面向过程 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

  • 相关阅读:
    NoSQL数据库:Redis内存使用优化与存储
    http缓存与cdn相关技术
    sphinx 全文索引
    Elasticsearch7.1中文文档-第一章-入门
    创建一个新的laravel
    mysql数据库的主从同步,实现读写分离
    使用 Swoole 来加速你的 Laravel 应用
    Linux下全局安装composer方法
    Laravel 加载第三方类库的方法
    jquery里把数组转换成json的方法
  • 原文地址:https://www.cnblogs.com/LoveJenny/p/2182007.html
Copyright © 2020-2023  润新知