1. 程式人生 > >PHP設計模式 五 (觀察者 策略 裝飾器模式)

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();