英雄與行為,依賴的誕生
首先定義一個英雄,英雄具有一些行為:
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);
}
}
隨着行為的增加,暴露出了幾個問題:
- 每增加一種行為,就必須修改一次英雄類;
- 如果想讓不同的英雄擁有不同的技能,需要創建很多不同的英雄類。
通過工廠模式,實現依賴轉移
定義一個行為工廠,英雄出生時可以在行為工廠中挑選行為:
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' => [],
]);
引入工廠模式,我們解決了上述的兩個問題:
- 使得英雄類不再依賴其他行為類,增加任意一種行為,都不需要修改英雄類;
- 如果想要不同的英雄擁有不同的技能,在英雄出生時選擇即可。
但同時我們也引入了一個新的問題,每增加一種行為,就需要在工廠中增加一條生產線。
后面,我們將講解如果使用一個更高級的工廠-服務容器來解決工廠模式存在的問題。