PHP設計模式 五 (觀察者 策略 裝飾器模式)
觀察者模式
觀察者模式(有時又被稱為釋出-訂閱Subscribe>模式、模型-檢視View>模式、源-收聽者Listener>模式或從屬者模式)是軟體設計模式的一種。在此種模式中,一個目標物件管理所有相依於它的觀察者物件,並且在它本身的狀態改變時主動發出通知。這通常透過呼叫各觀察者所提供的方法來實現。此種模式通常被用來實現事件處理系統。
當一個物件的狀態發生改變時,依賴他的物件全部會接到通知,並自動更新。觀察者模式實現了低耦合 非入侵式的通知與更新機制。
觀察者模式示例:
首先建立一個事件生成器 EventGenerator.php
<?php namespace Components\ObServer; abstract class EventGenerator { private $obServers = array(); function addObServer(IObServer $obServer) {//新增事件 $this->obServers[] = $obServer; } function notify() { foreach ($this->obServers as $obServer) {//一一執行更新 $obServer->update(); } } }
建立一個觀察者介面IObServer.php
<?php
namespace Components\ObServer;
interface IObServer {
function update($event_info = NULL);
}
事件主體:
class Event extends \Components\ObServer\EventGenerator{
function tringger() {
echo "<br>Event<br/>";
$this->notify();
}
}
觀察者:
//觀察者1 class ObServer1 implements \Components\ObServer\IObServer { function update($event_info = null) { echo "logic1<br>"; } } //觀察者2 class ObServer2 implements \Components\ObServer\IObServer { function update($event_info = null) { echo "logic2<br>"; } }
觸發:
$event = new Event();
$event->addObServer(new ObServer1());
$event->addObServer(new ObServer2());
$event->tringger();
策略模式
將一組特定的行為和演算法封裝成類,以適應某些特定的上下文環境,這就是策略模式。
應用場景:
1、 多個類只區別在表現行為不同,可以使用Strategy模式,在執行時動態選擇具體要執行的行為。
2、 需要在不同情況下使用不同的策略(演算法),或者策略還可能在未來用其它方式來實現。
3、 對客戶隱藏具體策略(演算法)的實現細節,彼此完全獨立。
組成
1、抽象策略角色: 策略類,通常由一個介面或者抽象類實現。
2、具體策略角色:包裝了相關的演算法和行為。
3、環境角色:持有一個策略類的引用,最終給客戶端呼叫。
分類廣告策略示例:
抽象策略角色
vim Istrategy.php
<?php
namespace Components\Strategy;
/**
* 策略模式 介面
* @author YUNDUAN
*
*/
interface IStrategy{
function showAd();
function showCategory();
}
具體策略角色
vim FemaleUser.php
<?php
namespace Components\Strategy;
class FemaleUser implements IStrategy {
function showAd() {
echo '女性廣告<br>';
}
function showCategory() {
echo '女裝<br>';
}
}
vim MaleUser.php
<?php
namespace Components\Strategy;
class MaleUser implements IStrategy {
function showAd() {
echo '男性廣告<br>';
}
function showCategory() {
echo '電子產品<br>';
}
}
環境角色:
vim Home.php
/**
* 策略模式 解耦和
* @author YUNDUAN
*
*/
class Home {
protected $strategy;
function index() {
echo "AD:";
$this->strategy->showAd();
echo "Category:";
$this->strategy->showCategory();
}
function setStrategy(Components\Strategy\IStrategy $strategy) {
//依賴注入 注入一個物件
$this->strategy = $strategy;
}
}
使用:
$home = new Home();
if (isset($_GET['female'])) {
$strategy = new \Components\Strategy\FemaleUser();
}else {
$strategy = new \Components\Strategy\MaleUser();
}
/*策略模式*/
$home->setStrategy($strategy);
$home->index();
裝飾器模式
在不必改變原類檔案和使用繼承的情況下,動態地擴充套件一個物件的功能。它是通過建立一個包裝物件,也就是裝飾來包裹真實的物件。
裝飾器介面IDecorator.php:
<?php
namespace Components\Decorator;
/**
* 裝飾器模式 介面
* @author WH
*
*/
interface IDecorator {
function before();
function after();
}
裝飾器1 DecoratorAttr1.php:
<?php
namespace Components\Decorator;
class DecoratorAttr1 implements IDecorator{
function before() {
echo '<br><div style="color:red">';
}
function after() {
echo '</div>';
}
}
裝飾器2 DecoratorAttr2.php:
<?php
namespace Components\Decorator;
class DecoratorAttr2 implements IDecorator{
function before() {
echo '<br><div style="font-size:30px">';
}
function after() {
echo '</div>';
}
}
使用:
/* 裝飾器模式 原類 */
class DecoratorClassTest {
protected $decorators = array();
//新增裝飾器
function addDecorator(\Components\Decorator\IDecorator $decorator) {
$this->decorators[] = $decorator;//新增裝飾器
}
function before(){
foreach ($this->decorators as $decorator) {
$decorator->before();//呼叫裝飾器
}
}
function after(){
//這裡可用棧
$decorators = array_reverse($this->decorators);
foreach ($decorators as $decorator) {
$decorator->after();//結束裝飾器
}
}
function test() {
$this->before();
echo 'running<be>';
$this->after();
}
}
$decoratorTest = new DecoratorClassTest();
$decoratorTest->addDecorator(new \Components\Decorator\DecoratorAttr1());
$decoratorTest->addDecorator(new \Components\Decorator\DecoratorAttr2());
$decoratorTest->test();
策略模式
將一組特定的行為和演算法封裝成類,以適應某些特定的上下文環境,這就是策略模式。
應用場景:
1、 多個類只區別在表現行為不同,可以使用Strategy模式,在執行時動態選擇具體要執行的行為。
2、 需要在不同情況下使用不同的策略(演算法),或者策略還可能在未來用其它方式來實現。
3、 對客戶隱藏具體策略(演算法)的實現細節,彼此完全獨立。
組成
1、抽象策略角色: 策略類,通常由一個介面或者抽象類實現。
2、具體策略角色:包裝了相關的演算法和行為。
3、環境角色:持有一個策略類的引用,最終給客戶端呼叫。
分類廣告策略示例:
抽象策略角色
vim Istrategy.php
<?php
namespace Components\Strategy;
/**
* 策略模式 介面
* @author YUNDUAN
*
*/
interface IStrategy{
function showAd();
function showCategory();
}
具體策略角色
vim FemaleUser.php
<?php
namespace Components\Strategy;
class FemaleUser implements IStrategy {
function showAd() {
echo '女性廣告<br>';
}
function showCategory() {
echo '女裝<br>';
}
}
vim MaleUser.php
<?php
namespace Components\Strategy;
class MaleUser implements IStrategy {
function showAd() {
echo '男性廣告<br>';
}
function showCategory() {
echo '電子產品<br>';
}
}
環境角色:
vim Home.php
/**
* 策略模式 解耦和
* @author YUNDUAN
*
*/
class Home {
protected $strategy;
function index() {
echo "AD:";
$this->strategy->showAd();
echo "Category:";
$this->strategy->showCategory();
}
function setStrategy(Components\Strategy\IStrategy $strategy) {
//依賴注入 注入一個物件
$this->strategy = $strategy;
}
}
使用:
$home = new Home();
if (isset($_GET['female'])) {
$strategy = new \Components\Strategy\FemaleUser();
}else {
$strategy = new \Components\Strategy\MaleUser();
}
/*策略模式*/
$home->setStrategy($strategy);
$home->index();