首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 設計模式:委派模式完整實作與 CD 播放器重構範例

     編輯:PHP 綜合知識

委派模式核心概念

兩個物件參與同一請求處理,接收請求的物件將工作委派給另一個物件完成。許多模式 (State, Strategy, Visitor) 本質上都是特定場景下的委派模式。

動態委派實作 (反射機制)

class Fruit {
    public function callFruit() { print "Generate an Apple"; }
}

class FruitDelegator {
    private $targets = [];
    public function __construct() { $this->targets[] = new Fruit(); }
    public function __call($name, $args) {
        foreach ($this->targets as $obj) {
            $r = new ReflectionClass($obj);
            if ($method = $r->getMethod($name)) {
                if ($method->isPublic() && !$method->isAbstract()) {
                    return $method->invoke($obj, $args);
                }
            }
        }
    }
}

$obj = new FruitDelegator();
$obj->callFruit(); // 輸出: Generate an Apple

可擴展委派器

class Color {
    public function callColor() { print "Generate Red"; }
}

class ColorDelegator {
    private $targets = [];
    public function addObject($obj) { $this->targets[] = $obj; }
    public function __call($name, $args) {
        foreach ($this->targets as $obj) {
            $r = new ReflectionClass($obj);
            if ($method = $r->getMethod($name)) {
                if ($method->isPublic() && !$method->isAbstract()) {
                    return $method->invoke($obj, $args);
                }
            }
        }
    }
}

$obj = new ColorDelegator();
$obj->addObject(new Color());
$obj->callColor(); // Generate Red

CD 播放器重構案例

重構前:條件判斷散落在客戶端

class CD {
    protected $cdInfo = [];
    public function addSong($song) { $this->cdInfo[$song] = $song; }
    public function playMp3($song) { return $this->cdInfo[$song] . '.mp3'; }
    public function playMp4($song) { return $this->cdInfo[$song] . '.mp4'; }
}

$cd = new CD();
$cd->addSong("1"); $cd->addSong("2"); $cd->addSong("3");
$type = 'mp3';
if ($type == 'mp3') { $cd->playMp3(); } else { $cd->playMp4(); }

重構後:委派模式封裝播放策略

namespace Tools;

// 委派介面
interface Delegate {
    public function playList($list, $song);
}

// 具體策略:MP3
class Mp3 implements Delegate {
    public function playList($list, $song) { return $list[$song] . '.mp3'; }
}

// 具體策略:MP4
class Mp4 implements Delegate {
    public function playList($list, $song) { return $list[$song] . '.mp4'; }
}

// 核心類別:委派給策略物件
class CDDelegate {
    protected $cdInfo = [];
    public function addSong($song) { $this->cdInfo[$song] = $song; }
    public function play($type, $song) {
        $className = '\\Tools\\' . ucfirst(strtolower($type)); // Mp3/Mp4
        $strategy = new $className();
        return $strategy->playList($this->cdInfo, $song);
    }
}

$cd = new CDDelegate();
$cd->addSong("1"); $cd->addSong("2"); $cd->addSong("3");
echo $cd->play('mp3', '1'); // 1.mp3 - 僅傳遞參數,自動選擇策略

播放清單委派完整範例

class PlayList {
    private $_songs = [];
    private $_object = null;
    public function __construct($type) {
        $class = $type . "PlayListDelegation";
        $this->_object = new $class();
    }
    public function addSong($location, $title) {
        $this->_songs[] = ['location'=>$location, 'title'=>$title];
    }
    public function getPlayList() {
        return $this->_object->getPlayList($this->_songs);
    }
}

class Mp3PlayListDelegation {
    public function getPlayList($songs) {
        return array_filter($songs, function($item) {
            return pathinfo($item['location'], PATHINFO_EXTENSION) === 'mp3';
        });
    }
}

class RmvbPlayListDelegation {
    public function getPlayList($songs) {
        return array_filter($songs, function($item) {
            return pathinfo($item['location'], PATHINFO_EXTENSION) === 'rmvb';
        });
    }
}

$mp3List = new PlayList("mp3");
$rmvbList = new PlayList("rmvb");

委派模式 vs 策略模式

維度委派模式策略模式
關係廣義概念委派模式的具體化形式
介面不強制要求統一介面 (Strategy Interface)
切換時機靜態/動態皆可運行時動態切換
核心目的職責分離、代理轉發算法族群封裝、可互換

最佳實踐建議

  1. 定義清晰的委派介面,確保策略類別可互換
  2. 核心類別不應包含條件判斷,單純轉發
  3. 策略建立可用工廠模式或依賴注入管理
  4. 配合單一職責原則:核心類別管資料,策略類別管行為
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved