你真的是在使用面向对象吗?

虽然现在都是使用面向对象,但你真的使用面向对象了吗?还是你一直在使用过程式编程

区别

面向对象和过程式编程的一个核心区别是:如何分配职责。过程式编程表现为一系列的命令和方法的连续调用。控制代码根据不同的条件执行不同的职责。面向对象编程将职责从客户端代码移到专门的对象中,尽量减少相互依赖。我们举个例子说明:

面向过程式的编程:

我们先用下面的格式来读写文本,readParam读取文件内容,然后存到关联数组里,最后返回。writeParam 函数会循环遍历关联数组,然后将键值对写入文件。

function readParam($sourceFile){
        $param = [];
        //从$sourceFile读取文件内容
        return $param;
}
function writeParam($param, $sourceFile){
        //写到$sourceFile文件里
}

上面这个工具好理解,也易于维护,但现在需求改变,需要支持读写xml和text文件。我们进一步改变代码,如下所示:

class file{
    function readParam($source){
        $param = [];
        if (preg_match("/\.xml$/i", $source)) {
            //从xml文件中读;
        } else {
            //从text文件中读
        }
        return $param;
    }
    function writeParam($param, $source)
    {
        if (preg_match("/\.xml$/i", $source)) {
            //写xml参数到文件中;
        } else {
            //写text参数到文件中
        }
    }
}

面向对象的编程:

abstract class ParamHandle
{
    protected $params = [];
    protected $source;
    public function __construct($source)
    {
        $this->source = $source;
    }

    public function addParam($key, $value)
    {
       $this->params[$key] = $value;
    }
    public function getAllParams()
    {
        return $this->params;
    }
    /**
     * 获得实例
     * @param $filename
     * @return object
     * */
    static function getInstance($filename)
    {
        if (preg_match("/\.xml$/i", $filename)) {
            return new XmlHandle($filename);
        } else {
            return new TextHandle($filename);
        }
    }
    abstract function read();
    abstract function write();
}
class XmlHandle extends ParamHandle
{
    public function read()
    {
        echo 'this is xml file read' . PHP_EOL;

        // TODO: Implement read() method.
        //读取xml文件内容,并赋值给$this->params
        $this->addParam('a', 'aa');
        $this->addParam('b', 'bb');
        $this->addParam('c', 'cc');
        return $this->getAllParams();
    }
    public function write()
    {
        echo 'this is xml file write' . PHP_EOL;
        // TODO: Implement write() method.
        //写入xml文件,使用$this->params
        $data = $this->params;
        echo '<pre>';
        print_r($data);
        exit;

    }
}
class TextHandle extends ParamHandle
{
    public function read()
    {
        echo 'this is text file read' . PHP_EOL;

        // TODO: Implement read() method.
        //读取xml文件内容,并赋值给$this->params
        $this->addParam('a', 'aa');
        $this->addParam('b', 'bb');
        $this->addParam('c', 'cc');
        return $this->getAllParams();
    }
    public function write()
    {
        echo 'this is text file write' . PHP_EOL;

        // TODO: Implement write() method.
        //写入xml文件,使用$this->params
        $data = $this->params;
        echo '<pre>';
        print_r($data);
        exit;
    }
}

$source = './param.xml';
$type = (int)$_GET['type'];
if ($type) {
    $instance = ParamHandle::getInstance($source);
    $instance->addParam('a', 'aa');
    $instance->addParam('b', 'bb');
    $instance->addParam('c', 'cc');
    $instance->addParam('d', 'dd');
    $instance->write();
} else {
    $instance = ParamHandle::getInstance($source);
    $data = $instance->read();
    echo '<pre>';
    print_r($data);
    exit;
}

echo 'ok';

说明:

  • 职责
    • 过程式编程: 条件语句被绑定到函数,判断流程被隐藏起来;忙于处理细节
    • 面向对象: 静态方法getInstance()进行格式化选择;只需要一个接口即可工作
  • 内聚:是一个模块内部各成分之间关联程度的度量。理想情况下,应该各组件职责清晰、分工明确。如果代码间的关联范围太广,维护就会很困难---因为修改某部分代码的同时需要修改相关的代码
    • 前面ParamHandle类将相关的处理集中起来,用于处理XML类的方法间可以共享数据,并且一个类方法中的改变可以很容易反映到另一个方法中,可以说ParamHandle是高度内聚的。过程式的例子,把相关的过程分离开,导致处理XML的代码在多个函数中同时出现
  • 耦合:当系统各个部分代码紧密绑在一起时就会产生紧密耦合,这时一个组件的改变会迫使其他部件随之改变。过程式代码容易产生耦合问题。例如在过程示例中,writeParam和readParam中,使用了相同文件扩展名测试来决定如何处理数据。因此要改写一个函数就不得不同时改写另一个函数。例如增加一种新的文件格式,就要在两个函数中按相同的方式都加上相应的扩展名检查代码,这样两个函数才能保持一致。面向对象的示例则将每个子类彼此分开,也将其与客户端分开。如果需要新增参数格式。只需要简单地创建相应的子类,并在父类中的静态方法getInstance()中增加一行文件检测代码即可。
  • 正交:指将职责相关的组件紧紧组合在一起,与系统环境隔开,保持独立。正交主张重用组件,期望不需要任何特殊配置就能把一个组件插入到新系统中,这样的组件有明确的与环境无关的输入和输出。正交代码使修改变简单,因为修改一个只会影响到被改动的组件本身。正交代码更加安全。bug的影响只局限于他的作用域之中。内部高度相互依赖的代码发生错误时,很容易在系统中引起连锁反应。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值