轉載請注明作者和出處:http://www.itdecent.cn/p/fceff41be9d1
運行平臺: Windows
php版本: php7.0
策略模式,簡單來說,就是完成不同的的任務,卻用相同的方法來實現(xiàn),我們可能見過用到策略模式的地方就是php框架中,封裝了針對不同數(shù)據庫的方法,可是我們卻都能用同一種方法調用他們,我是這么理解的,如果有什么錯誤的地方歡迎指正。
- 環(huán)境角色(Context):持有一個Strategy的引用
- 抽象策略(Strategy)角色:這是一個抽象角色,通常由一個接口或抽象類實現(xiàn)。此角色給出所有的具體的策略類所需的接口
- 具體策略(ConcreateStrategy)角色:包裝了相關的算法或行為
常用英文單詞:Strategy,Context
最好把設計模式常用的英文單詞用熟,這樣在你閱讀源代碼的時候有很大的幫助,往往大神寫的代碼注釋很少,但是他們的變量名,方法名都符合規(guī)范,你看到這個單詞就知道是怎么一回事,這比無用的注釋好了很多
//定義一個規(guī)范,抽象策略類
abstract class Strategy{
//小明上學的方法
abstract function Way();
}
//騎自行車類
class BikeStrategy extends Strategy{
public function Way()
{
echo "騎自行車上學咯";
}
}
//小車類
class CarStrategy extends Strategy{
public function Way()
{
echo "開車上學咯";
}
}
//走路上學類
class WalkStrategy extends Strategy{
public function Way()
{
echo "走路上學咯";
}
}
class SchoolContext{
private $strategy;//獲取具體策略
public function __construct(Strategy $strategy)//參數(shù)設定為繼承Strategy接口的子類
{
$this->strategy= $strategy;
}
public function useRun(){
$this->strategy->Way();
}
}
$school = new SchoolContext(new BikeStrategy());
$school->useRun();//騎自行車上學咯
$school = new SchoolContext(new WalkStrategy());
$school->useRun();//走路上學咯
這里我們把實例化的類作為一個參數(shù)注射(依賴注入,內部方法的實現(xiàn)依賴于外部實例化類)進入到學校類之中,我們使用類 Strategy $strategy 限制類必須為繼承Strategy接口的子類,這樣可以有效防止注入大炮火箭之類亂七八糟的東西,好了,那么我們看看策略模式的一些實際應用場景。
<?php
//分享類抽象接口
abstract class ShareStrategy{
//分享的標題
abstract function share_title();
//分享的作者
abstract function share_author();
//分享的文章
abstract function share_content();
}
//微信分享
class WechatShareStrategy extends ShareStrategy{
//分享的標題
public function share_title(){
//標題
}
//分享的作者
public function share_author(){
//作者
}
//分享的文章
public function share_content(){
//文章
}
}
//qq分享
class QQShareStrategy extends ShareStrategy{
//分享的標題
public function share_title(){
//標題
}
//分享的作者
public function share_author(){
//作者
}
//分享的文章
public function share_content(){
//文章
}
}
class ShareContext{
private $strategy;//保存對象
public function __construct(ShareStrategy $strategy)//參數(shù)設定為繼承Strategy接口的子類
{
$this->strategy = $strategy;
}
public function title(){
$this->strategy->share_title();
}
public function author(){
$this->strategy->share_author();
}
public function content(){
$this->strategy->share_content();
}
}
class ShareFactory{
static public function factory($strategy){
switch($strategy){
case 'wechat':
$object = new WechatShareStrategy();
break;
case 'qq':
$object = new QQShareStrategy();
break;
}
return $object;
}
}
class Article{
//分享
public function Share(){
$strategy = ShareFactory::factory('wechat');
$shareContext = new ShareContext($strategy);
$shareContext->title();//微信分享標題
$shareContext->author();//微信分享作者
$shareContext->content();//微信分享內容
}
}
我們這里結合上一章所學的簡單工廠實現(xiàn)了一個分享的簡單例子,當然,簡單工廠也有局限性,就是我們每次增加一個分享類,就要去工廠里增加方法,破化了類的開放封閉原則,我們可以結合類的反射來修改一下ShareFactory方法;
<?php
//分享類抽象接口
abstract class ShareStrategy{
//分享的標題
abstract function share_title();
//分享的作者
abstract function share_author();
//分享的文章
abstract function share_content();
}
//微信分享
class WechatShareStrategy extends ShareStrategy{
//分享的標題
public function share_title(){
echo 'wechat_title'."\n";
//標題
}
//分享的作者
public function share_author(){
echo 'wechat_author'."\n";
//作者
}
//分享的文章
public function share_content(){
echo 'wechat_content'."\n";
//文章
}
}
//qq分享
class QQShareStrategy extends ShareStrategy{
//分享的標題
public function share_title(){
echo 'qq_title';
//標題
}
//分享的作者
public function share_author(){
echo 'qq_author';
//作者
}
//分享的文章
public function share_content(){
echo 'qq_content';
//文章
}
}
class ShareContext{
private $strategy;//保存對象
public function __construct(ShareStrategy $strategy)//參數(shù)設定為繼承Strategy接口的子類
{
$this->strategy = $strategy;
}
public function title(){
$this->strategy->share_title();
}
public function author(){
$this->strategy->share_author();
}
public function content(){
$this->strategy->share_content();
}
}
class ShareFactory{
//返回實例化對象
static public function factory($strategy){
//$strategy為類的字符串名稱
$class = new ReflectionClass($strategy);
return $class->newInstance();
}
}
class Article{
//分享
static public function Share(){
$strategy = ShareFactory::factory('WechatShareStrategy');
$shareContext = new ShareContext($strategy);
$shareContext->title();//微信分享標題
$shareContext->author();//微信分享作者
$shareContext->content();//微信分享內容
}
}
Article::Share();
輸出結果

我們通過傳入類的字符串名稱,來進行動態(tài)的實例化類(在框架里一般還會配合spl_autoload_register()這個自動加載類來加載實現(xiàn)實例化類),關于這類實例化類還需要考慮構造函數(shù)的參數(shù)等等因素,我這里比較簡單的提一下,有需要的可以去百度查找一下更詳細的資料,或者以后在依賴注入這一章節(jié)會配合laravle核心ioc容器來詳細講解。