深入 Laravel 內核之工廠模式


英雄與行為,依賴的誕生

首先定義一個英雄,英雄具有一些行為:

class Hero {
    protected $behavior = [];

    public function show()
    {
        var_dump($this->behavior);
    }
}

然后定義一種名為攻擊行為:

class Attack {
    protected $value = 0;

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

改造一下英雄類,讓英雄在出生的時候具有攻擊行為:

class Hero {
    protected $behavior = [];

    public function __construct()
    {
        array_push($this->behavior, new Attack(10));
    }

    public function show()
    {
        var_dump($this->behavior);
    }
}

這樣,英雄和某個具體的行為就產生了一種依賴關系。

英雄學會了越來越多的行為

隨着英雄的成長,英雄學會了越來越多的行為:

class Defend {
    protected $value = 0;
    public function __construct($value){}
}

class Move {
    protected $speed;
    public function __construct($speed){}
}

class Skill1 {
    protected $name = '暴擊';
    public function __construct(){}
}

class Skill2 {
    protected $name = '眩暈';
    public function __construct(){}
}

改造一下英雄類,讓英雄在出生的時候具有這些行為:

class Hero {
    protected $behavior = [];

    public function __construct()
    {
        array_push($this->behavior, new Attack(10));
        array_push($this->behavior, new Defend(5));
        array_push($this->behavior, new Move(30));
        array_push($this->behavior, new Skill1());
        array_push($this->behavior, new Skill2());
    }

    public function show()
    {
        var_dump($this->behavior);
    }
}

隨着行為的增加,暴露出了幾個問題:

  1. 每增加一種行為,就必須修改一次英雄類;
  2. 如果想讓不同的英雄擁有不同的技能,需要創建很多不同的英雄類。

通過工廠模式,實現依賴轉移

定義一個行為工廠,英雄出生時可以在行為工廠中挑選行為:

class BehaviorFactory
{
    public function makeBehavior($behaviorName, $options=[])
    {
        switch ($behaviorName) {
            case 'Attack':   return new Attack($options[0]);
            case 'Defend':   return new Defend($options[0]);
            case 'Move':     return new Move($options[0]);
            case 'Skill1':   return new Skill1();
            case 'Skill2':   return new Skill2();
        }
    }
}

修改英雄類,讓英雄可以去工廠中學習行為:

class Hero
{
    protected $behavior = [];

    public function __construct(array $behaviors)
    {
        // 初始化工廠
        $factory = new BehaviorFactory();

        // 通過工廠提供的方法制造需要的模塊
        foreach ($behaviors as $behaviorName => $behaviorOptions) {
            $this->behavior[] = $factory->makeBehavior($behaviorName, $behaviorOptions);
        }
    }
}

$hero = new Hero([
	'Attack' => [10],
	'Defend' => [5],
	'Move'   => [30],
	'Skill1' => [],
]);

引入工廠模式,我們解決了上述的兩個問題:

  1. 使得英雄類不再依賴其他行為類,增加任意一種行為,都不需要修改英雄類;
  2. 如果想要不同的英雄擁有不同的技能,在英雄出生時選擇即可。

但同時我們也引入了一個新的問題,每增加一種行為,就需要在工廠中增加一條生產線。

后面,我們將講解如果使用一個更高級的工廠-服務容器來解決工廠模式存在的問題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM