PHP 設計模式之責任鏈模式

echo_dump發表於2020-06-17

責任鏈模式 Chain Of Responsibilities

顧名思義,責任鏈模式(Chain of Responsibility Pattern)為請求建立了一個接收者物件的鏈。這種模式給予請求的型別,對請求的傳送者和接收者進
行解耦。這種型別的設計模式屬於行為型模式。在這種模式中,通常每個接收者都包含對另一個接收者的引用。如果一個物件不能處理該請求,那麼它會把相同的
請求傳給下一個接收者,依此類推。

  1. 責任鏈模式也是屬於行為型模式

  2. 責任鏈模式是有一個請求類,一個請求處理者抽象類,然後有多個請求處理者字類去處理請求

  3. 比如現在有一個場景,有一個學校,學校平時需要採購一些物品,比如粉筆,黑板擦,垃圾桶,掃帚,大一點的物品,智慧課堂的電子裝置,學生桌椅的報修,
    周圍環境的裝修呀,老師的備課用品呀等等,一些小的物品,比如3000元一下的,可能一個管後勤的小科員就可以直接簽字同意,一些3000-4500元的物品,就
    需要主任來簽字同意了,再大一點的4500-10000就需要副校長簽字同意了,那麼再大一點10000-50000的就需要校長來簽字了,大於50000的就需要教育局來
    報備了,就不是學校可以自行決定的了。

  4. 根據3的物理場景,就可以使用職責鏈模式了,購買物品就是一個請求,需要對應的請求處理者(小科員,主任,副校長,校長)來處理。

  5. 比如請求處理,可以定義一個請求類,Request,可以把請求類做成一個介面,然後去實現它,這裡只是做實驗,就只作一個類,不去些介面了

class Request
{
    public $id = 0;

    public $price = 0;

    public $type = 1;

    public $desc = '';

    public function __construct(int $id = 0, int $price = 0, int $type = 1, string $desc = '')
    {
        $this->id = $id;

        $this->price = $price;

        $this->type = $type;

        $this->desc = $desc;
    }

    public function getId()
    {
        return $this->id;
    }

    public function getType()
    {
        return $this->type;
    }

    public function getPrice()
    {
        return $this->price;
    }

    public function getDesc()
    {
        return $this->desc;
    }
}
  1. 定義一個請求處理抽象類,這個抽象類定義三個方法,一個是__construct(Request $request),它接受一個請求類Request,
    第二個方法是final public function requestHandle(RequestHandleAbstract $abstract),它會接受一個自身的抽象類引數,把當前處理者處理
    不了的問題,指向下一個處理者,第三個方法就是當前的處理者的具體操作abstract public function processHandle();它是一個抽象方法
abstract class RequestHandleAbstract
{
    protected $request;

    public function __construct(Request $request)
    {
        $this->request = $request;
    }

    /**
     * Notes:指向下一個請求
     * Name: requestHandle
     * User: LiYi
     * Date: 2020/6/16
     * Time: 22:20
     * @param RequestHandleAbstract $abstract
     * @return mixed
     */
    final public function requestHandle(RequestHandleAbstract $abstract)
    {
        $abstract->processHandle();
    }

    /**
     * Notes:具體的處理請求程式
     * Name: processHandle
     * User: LiYi
     * Date: 2020/6/16
     * Time: 22:21
     * @return mixed
     */
    abstract public function processHandle();
}
  1. 分別定義科員,主任,父校長,校長的處理請求的具體實現類
class ClerkSchool extends RequestHandleAbstract
{
    public function processHandle()
    {
        // TODO: Implement processHandle() method.
        if ($this->request->getPrice() <= 3000) {
            echo '此次請求的任務是: '.$this->request->getDesc() . ' 請求的id是:' . $this->request->getId() . ' 請求的型別是:'
                . $this->request->getType() . ' 此次批覆的金額為:' . $this->request->getPrice(). PHP_EOL;
            echo '處理人是科員' . PHP_EOL;
        } else {
            $this->requestHandle(new DirectorSchool($this->request));
        }
    }
}

class DirectorSchool extends RequestHandleAbstract
{
    public function processHandle()
    {
        // TODO: Implement processHandle() method.
        if ($this->request->getPrice() > 3000 && $this->request->getPrice() <= 4500) {
            echo '此次請求的任務是: '.$this->request->getDesc() . ' 請求的id是:' . $this->request->getId() . ' 請求的型別是:'
                . $this->request->getType() . ' 此次批覆的金額為:' . $this->request->getPrice(). PHP_EOL;
            echo '處理人是主任' . PHP_EOL;
        } else {
            $this->requestHandle(new VicePrincipalSchool($this->request));
        }
    }
}

class VicePrincipalSchool extends RequestHandleAbstract
{
    public function processHandle()
    {
        // TODO: Implement processHandle() method.
        if ($this->request->getPrice() > 4500 && $this->request->getPrice() <= 10000) {
            echo '此次請求的任務是: '.$this->request->getDesc() . ' 請求的id是:' . $this->request->getId() . ' 請求的型別是:'
                . $this->request->getType() . ' 此次批覆的金額為:' . $this->request->getPrice(). PHP_EOL;
            echo '處理人是副校長' . PHP_EOL;
        } else {
            $this->requestHandle(new PrincipalSchool($this->request));
        }
    }
}

class PrincipalSchool extends RequestHandleAbstract
{
    public function processHandle()
    {
        // TODO: Implement processHandle() method.
        // TODO: Implement processHandle() method.
        if ($this->request->getPrice() > 10000 && $this->request->getPrice() <= 50000) {
            echo '此次請求的任務是: '.$this->request->getDesc() . ' 請求的id是:' . $this->request->getId() . ' 請求的型別是:'
                . $this->request->getType() . ' 此次批覆的金額為:' . $this->request->getPrice(). PHP_EOL;
            echo '處理人是校長' . PHP_EOL;
        } else {
            echo '超出職責範圍處理不了' . PHP_EOL;
        }
    }
}
  1. 測試,我們使用隨機的需要採購物品的價格,來測試,看看不同的價格,最後是不是按照我們的想法得到處理的
class Client
{
    public function __construct()
    {
        $request = new Request(mt_rand(1111, 9999), mt_rand(1, 99999), mt_rand(1, 9), '學校裝修新電子教室');

        $clerk = new ClerkSchool($request);

        $clerk->processHandle();
    }
}

require '../vendor/autoload.php';
new Client();
本作品採用《CC 協議》,轉載必須註明作者和本文連結
LIYi ---- github地址

相關文章