策略模式 Strategy
策略模式在分類上屬於行為型
現在有一個例子,比如有一隻鴨子,有的鴨子是會飛的(野鴨),有的鴨子不會飛(家裡養的鴨子),有的鴨子是會瓜瓜叫的,有的鴨子就不會叫(玩具鴨,
周黑鴨),有的鴨子會游泳(養的鴨子,野鴨),有的鴨子不會(周黑鴨,玩具鴨,小黃鴨)假如利用繼承來實現,那就是先建立一個抽象類,然後野鴨,周黑鴨,家裡養的鴨子,小黃鴨,玩具鴨,都要去繼承我們的抽象類鴨子,
<?php
namespace Strategy;
abstract class DuckTest
{
/**
* Notes:介紹鴨子
* Name: display
* User: LiYi
* Date: 2020/6/15
* Time: 23:44
* @param string $name
* @return mixed
*/
public function display(string $name)
{
echo "我是: " . $name;
}
public function call()
{
echo '鴨子都會叫' . PHP_EOL;
}
public function fly()
{
echo '鴨子都會飛' . PHP_EOL;
}
public function swim()
{
echo '鴨子都會游泳' . PHP_EOL;
}
}
- 抽象類裡有很多方法,可能對不同的鴨子,很多都不適用,那麼就需要去重寫它,每一個種類的鴨子都要去重寫這個抽象類的方法,這樣做,很不實用。那麼
有沒有一個辦法不去重寫這個抽象類呢,其實是有的。比如,還建立一個抽象類的鴨子,鴨子會不會飛,會不會叫,會不會游泳,這三個屬性都把它作為一個介面
<?php
namespace Strategy;
abstract class Duck
{
protected $fly = null;
protected $call = null;
protected $swim = null;
/**
* Notes:介紹鴨子
* Name: display
* User: LiYi
* Date: 2020/6/15
* Time: 23:44
* @param string $name
* @return mixed
*/
public function display(string $name)
{
echo "我是: " . $name . PHP_EOL;
}
public function call()
{
if (!is_null($this->call)) {
$this->call->call();
}
}
public function fly()
{
if (!is_null($this->fly)) {
$this->fly->fly();
}
}
public function swim()
{
if (!is_null($this->swim)) {
$this->swim->swim();
}
}
}
- 定義三個介面來描述鴨子的各種能力
namespace Strategy;
interface CallInterface
{
public function call();
}
interface FlyInterface
{
public function fly();
}
interface SwimInterface
{
public function swim();
}
- 每種鴨子的能力都不相同,會飛的,不會飛的,飛的不怎樣的,會叫的,不會叫的,叫不出來的,等等,每種能力都有各自的實現。
class NoFly implements FlyInterface
{
public function fly()
{
// TODO: Implement fly() method.
echo "我是不會飛的鴨子" . PHP_EOL;
}
}
class GoodFly implements FlyInterface
{
public function fly()
{
// TODO: Implement fly() method.
echo '我是一個飛的還可以的鴨子' . PHP_EOL;
}
}
class BadFly implements FlyInterface
{
public function fly()
{
// TODO: Implement fly() method.
echo '我是一個飛的不怎麼樣的鴨子' . PHP_EOL;
}
}
class GuaGuaCall implements CallInterface
{
public function call()
{
// TODO: Implement call() method.
echo '我是一個呱呱叫的鴨子';
}
}
class LowVoiceCall implements CallInterface
{
public function call()
{
// TODO: Implement call() method.
echo '我只會小聲叫的鴨子' . PHP_EOL;
}
}
class NoCall implements CallInterface
{
public function call()
{
// TODO: Implement call() method.
echo '我是一個不會叫的鴨子' . PHP_EOL;
}
}
- 假如現在有一個野鴨,和一個小黃鴨,那麼我們就可以根據鴨子的各自屬性,來組合鴨子的各自能力,就不需要去重寫抽象類的方法了
class WildDuck extends Duck
{
public function __construct()
{
$this->fly = new GoodFly();
$this->call = new LowVoiceCall();
}
}
class YellowDuck extends Duck
{
public function __construct()
{
$this->fly = new BadFly();
$this->call = new NoCall();
}
}
- 最後測試
class Client
{
public function __construct()
{
$wildDuck = new WildDuck();
$wildDuck->display('野鴨');
$wildDuck->fly();
$wildDuck->swim();
$wildDuck->call();
$yellowDuck = new YellowDuck();
$yellowDuck->display('小黃鴨');
$yellowDuck->fly();
$yellowDuck->swim();
$yellowDuck->call();
}
}
require '../vendor/autoload.php';
new Client();
/**
* 我是: 野鴨
我是一個飛的還可以的鴨子
我只會小聲叫的鴨子
我是: 小黃鴨
我是一個飛的不怎麼樣的鴨子
我是一個不會叫的鴨子
*/
本作品採用《CC 協議》,轉載必須註明作者和本文連結
LIYi ---- github地址