声明:本文并非博主原创,而是来自对《Laravel 4 From Apprentice to Artisan》阅读的翻译和理解,当然也不是原汁原味的翻译,能保证90%的原汁性,另外因为是理解翻译,肯定会有错误的地方,欢迎指正。

欢迎转载,转载请注明出处,谢谢!

单一责任原则

介绍

“SOLID”设计原则,是Robert “Uncle Bob” Martin提出的理论。它是良好应用设计的5大原则,包含:

  • 单一责任原则

  • 开放封闭原则

  • 里氏替换原则

  • 接口分离原则

  • 依赖倒置原则

让我们通过代码示例来深究下这五个原则。这5个原则相互****,一荣俱荣,一毁俱毁。

实探

单一责任原则代表一个类有且仅有一个改变的原因,换言之,一个类的职责范畴是严谨明确的。我们之前说过对来说无知是福。类只需要干好自己的工作,对于其依赖变化的影响是无需感知的。

看下面这个类:

class OrderProcessor {

    public function __construct(BillerInterface $biller)
    {
        $this->biller = $biller;
    }

    public function process(Order $order)
    {
        $recent = $this->getRecentOrderCount($order);

        if ($recent > 0)
        {
            throw new Exception('Duplicate order likely.');
        }

        $this->biller->bill($order->account->id, $order->amount);

        DB::table('orders')->insert(array(
            'account' => $order->account->id,
            'amount' => $order->amount;
            'created_at' => Carbon::now();
        ));
    }

    protected function getRecentOrderCount(Order $order)
    {
        $timestamp = Carbon::now()->subMinutes(5);

        return DB::table('orders')
            ->where('account', $order->account->id)
            ->where('created_at', '>=', $timestamps)
            ->count();
    }

}

该类的职责是什么?通过名字可以明确他就是来处理订单的。但是,从getRecentOrderCount方法中又能看到该方法需要对数据库中的历史订单进行检测以判断是否重复订单。额外的验证意味着在数据存储改变的情况下,我们的订单处理程序必须要进行验证规则的修改。

我们可以把这个职责提取到单独的类OrderRepository中:

class OrderRepository {

    public function getRecentOrderCount(Account $account)
    {
        $timestamp = Carbon::now()->subMinutes(5);

        return DB::table('orders')
        ->where('account', $account->id)
        ->where('created_at', '>=', $timestamp)
        ->count();
    }

    public function logOrder(Order $order)
    {
        DB::table('orders')->insert(array(
            'account' => $order->account->id,
            'amount' => $order->amount;
            'created_at' => Carbon::now();
        ));
    }

}

然后在OrderProcessor中注入类库,来减少它检测账户历史订单的职责:

class OrderProcessor {

    public function __construct(BillerInterface $biller, OrderRepository $orders)
    {
        $this->biller = $biller;
        $this->orders = $orders;
    }

    public function process(Order $order)
    {
        $recent = $this->orders->getRecentOrderCount($order->account);

        if ($recent > 0)
        {
            throw new Exception('Duplicate order likely.');
        }

        $this->biller->bill($order->account->id, $order->amount);

        $this->orders->logOrder($order);
    }

}

现在我们将订单数据收集责任抽象出来,当获取记录订单的方法改变时,就无需再对OrderProcessor类进行修改了。现在的类库职责明确单一,代码简洁,表现力强,同时可维护性也大大的提升。

牢记,单一责任原则不是指代码越少越好,他是指写类是类的职责要非常明确,要有一套可用的方法,这些方法在类中要组成类的整体职责。根据既定的职责撰写出的这些巧而简洁的类,我们的代码就能是一个解耦的,可测的,可友好改变的架构。


laravel
101 声望55 粉丝