設計模式的作用:一方面將變化的東西封裝起來,另一方面將眾多的類抽象開防止類過多
1、簡單工廠模式
不同條件下創建不同實例

2、抽象工廠模式
簡單工廠模式有個問題,每添加一次新的類都要修改方法,不符合面向對象的開閉原則(對類的增加開放,對類的修改閉合)
抽象工廠模式便解決了這一問題,每次添加新的類就行了。

3、單例模式
保證一個類僅有一個實例
<?php namespace Test; class Database { //私有化內部實例化的對象 private static $instance = null; //私有化構造方法,禁止外部實例化 private function __construct(){} //私有化__clone,防止被克隆 private function __clone(){} // 公有靜態實例方法 public static function getInstance(){ if(empty(self::$instance)){ self::$instance=new Test(); } return self::$instance; } } $obj1=Test::getInstance(); $obj2=Test::getInstance(); echo $obj1==$obj2?1:0;
4、觀察者模式
一對多的依賴關系,在觀察目標類里有一個 ArrayList 存放觀察者們。當觀察目標對象的狀態發生改變,所有依賴於它的觀察者都將得到通知,使這些觀察者能夠自動更新(即使用推送方式)
主題提供注冊和通知的接口,觀察者提供自身操作的接口。(這些觀察者擁有一個同一個接口。)觀察者利用主題的接口向主題注冊,而主題利用觀察者接口通知觀察者。耦合度相當之低。
如何實現觀察者注冊?通過前面的注冊者模式很容易給我們提供思路,把這些對象加到一棵注冊樹上就好了嘛。如何通知?這就更簡單了,對注冊樹進行遍歷,讓每個對象實現其接口提供的操作。
<?php // 主題接口 interface Subject{ public function register(Observer $observer); public function notify(); } // 觀察者接口 interface Observer{ public function watch(); } // 主題 class Action implements Subject{ public $_observers=array(); public function register(Observer $observer){ $this->_observers[]=$observer; } public function notify(){ foreach ($this->_observers as $observer) { $observer->watch(); } } } // 觀察者 class Cat implements Observer{ public function watch(){ echo "Cat watches TV<hr/>"; } } class Dog implements Observer{ public function watch(){ echo "Dog watches TV<hr/>"; } } class People implements Observer{ public function watch(){ echo "People watches TV<hr/>"; } } // 應用實例 $action=new Action(); $action->register(new Cat()); $action->register(new People()); $action->register(new Dog()); $action->notify();
5、責任鏈模式
攔截的類都實現統一接口,每個接收者都包含對下一個接收者的引用。將這些對象連接成一條鏈,並且沿着這條鏈傳遞請求,直到有對象處理它為止。
<?php
//申請Model
class Request
{
//數量
public $num;
//申請類型
public $requestType;
//申請內容
public $requestContent;
}
//抽象管理者
abstract class Manager
{
protected $name;
//管理者上級
protected $manager;
public function __construct($_name)
{
$this->name = $_name;
}
//設置管理者上級
public function SetHeader(Manager $_mana)
{
$this->manager = $_mana;
}
//申請請求
abstract public function Apply(Request $_req);
}
//經理
class CommonManager extends Manager
{
public function __construct($_name)
{
parent::__construct($_name);
}
public function Apply(Request $_req)
{
if($_req->requestType=="請假" && $_req->num<=2)
{
echo "{$this->name}:{$_req->requestContent} 數量{$_req->num}被批准。<br/>";
}
else
{
if(isset($this->manager))
{
$this->manager->Apply($_req);
}
}
}
}
//總監
class MajorDomo extends Manager
{
public function __construct($_name)
{
parent::__construct($_name);
}
public function Apply(Request $_req)
{
if ($_req->requestType == "請假" && $_req->num <= 5)
{
echo "{$this->name}:{$_req->requestContent} 數量{$_req->num}被批准。<br/>";
}
else
{
if (isset($this->manager))
{
$this->manager->Apply($_req);
}
}
}
}
//總經理
class GeneralManager extends Manager
{
public function __construct($_name)
{
parent::__construct($_name);
}
public function Apply(Request $_req)
{
if ($_req->requestType == "請假")
{
echo "{$this->name}:{$_req->requestContent} 數量{$_req->num}被批准。<br/>";
}
else if($_req->requestType=="加薪" && $_req->num <= 500)
{
echo "{$this->name}:{$_req->requestContent} 數量{$_req->num}被批准。<br/>";
}
else if($_req->requestType=="加薪" && $_req->num>500)
{
echo "{$this->name}:{$_req->requestContent} 數量{$_req->num}再說吧。<br/>";
}
}
}
調用:
header("Content-Type:text/html;charset=utf-8");
//--------------------職責鏈模式----------------------
require_once "./Responsibility/Responsibility.php";
$jingli = new CommonManager("李經理");
$zongjian = new MajorDomo("郭總監");
$zongjingli = new GeneralManager("孫總");
//設置直接上級
$jingli->SetHeader($zongjian);
$zongjian->SetHeader($zongjingli);
//申請
$req1 = new Request();
$req1->requestType = "請假";
$req1->requestContent = "小菜請假!";
$req1->num = 1;
$jingli->Apply($req1);
$req2 = new Request();
$req2->requestType = "請假";
$req2->requestContent = "小菜請假!";
$req2->num = 4;
$jingli->Apply($req2);
$req3 = new Request();
$req3->requestType = "加薪";
$req3->requestContent = "小菜請求加薪!";
$req3->num = 500;
$jingli->Apply($req3);
$req4 = new Request();
$req4->requestType = "加薪";
$req4->requestContent = "小菜請求加薪!";
$req4->num = 1000;
$jingli->Apply($req4);
6、策略模式
策略對象依賴注入到context對象,context對象根據它的策略改變而改變它的相關行為(可通過調用內部的策略對象實現相應的具體策略行為)
<?php header('Content-Type:text/html;charset=utf-8'); /** * 策略模式演示代碼 * * 為了更好地突出“策略”,我們這里以出行為例演示,日常出行大概分為以下幾種工具:自駕車,公交車,地鐵,火車,飛機,輪船 * * 下面一起看代碼,領會何為策略模式 */ /** * Interface Travel 抽象策略角色 * 約定具體方法 */ interface Travel { public function go(); } /** * Class selfDriving 具體策略角色 * 自駕車 */ class bySelfDriving implements Travel { public function go() { echo '我自己開着車出去玩<br>'; } } /** * Class byBus具體策略角色 * 乘公交 */ class byBus implements Travel { public function go() { echo '我乘公交出去玩<br>'; } } /** * Class byMetro 具體策略角色 * 乘地鐵 */ class byMetro implements Travel { public function go() { echo '我乘地鐵出去玩<br>'; } } /** * Class byTrain 具體策略角色 * 乘火車 */ class byTrain implements Travel { public function go() { echo '我乘火車出去玩<br>'; } } /** * Class byAirplane 具體策略角色 * 乘飛機 */ class byAirplane implements Travel { public function go() { echo '我乘飛機出去玩<br>'; } } /** * Class bySteamship 具體策略角色 * 乘輪船 */ class bySteamship implements Travel { public function go() { echo '我乘輪船出去玩<br>'; } } /** * Class Mine 環境角色 */ class Mine{ private $_strategy; private $_isChange = false; /** * 構造方法 * 此處使用到了依賴注入和類型約束的概念,詳情請參考 * 1.聊一聊PHP的依賴注入(DI) 和 控制反轉(IoC) * @link https://segmentfault.com/a/1190000007209266 * 2.淺談PHP的類型約束 * @link https://segmentfault.com/a/1190000007226476 * * @param Travel $travel */ public function __construct(Travel $travel) { $this->_strategy = $travel; } /** * 改變出行方式 * * @param Travel $travel */ public function change(Travel $travel) { $this->_strategy = $travel; $this->_isChange = true; } public function goTravel() { if ($this->_isChange) { echo '現在改變主意,'; $this->_strategy->go(); } else { $this->_strategy->go(); } } } /** * 客戶端使用 */ $strategy = new Mine(new byBus()); // 乘公交 $strategy->goTravel(); // 乘地鐵 $strategy->change(new byMetro()); $strategy->goTravel(); // 自駕車 $strategy->change(new bySelfDriving()); $strategy->goTravel(); // 其他根據具體應用選擇實現
運行結果
7、裝飾器模式
保持接口,增強性能:修飾類繼承被修飾對象的抽象父類,依賴被修飾對象的實例(被修飾對象依賴注入),以實現接口擴展
基類傳入基本的數據,可通過后面的類進行加工處理,自主組合


8、適配器模式
使得原本由於接口不兼容而不能一起工作的那些類可以一起工作


9、橋接模式
兩個維度獨立變化,依賴方式實現抽象與實現分離:需要一個作為橋接的接口/抽象類,多個角度的實現類依賴注入到抽象類,使它們在抽象層建立一個關聯關系
類的組合完成業務邏輯


