<?php
/**
* 转自 《PHP设计模式》 第六章: 装饰器模式
*
* 装饰器设计模式适用于下列工作场合: 需求变化是快速和细小的,而且几乎不影响应用程序的其他部分。()
* 使用装饰器设计模式设计类的目标是: 不必重写任何已有的功能性代码,而是对某个基于对象应用增量变化。
* 装饰器设计模式采用这样的构建方式: 在主代码流中应该能够直接插入一个或多个更改或“装饰”目标对象的装饰器,同时不影响其他代码流。
*
*/
class CD {
public $trackList;
public function __construct() {
$this->trackList = array();
}
public function addTrack($track) {
$this->trackList[] = $track;
}
public function getTrackList() {
$output = '';
foreach ($this->trackList as $num => $track) {
$output .= ($num + 1) . ") {$track}.";
}
return $output;
}
}
$tracksFroExternalSource = array("What It Means", "Brr", "Goodbye");
$myCD = new CD();
foreach ($tracksFroExternalSource as $track) {
$myCD->addTrack($track);
}
print "The CD contains:{$myCD->getTrackList()}\n";
/**
* 需求发生小变化: 要求每个输出的参数都采用大写形式. 对于这么小的变化而言, 最佳的做法并非修改基类或创建父 - 子关系,
而是创建一个基于装饰器设计模式的对象。
*
*/
class CDTrackListDecoratorCaps {
private $_cd;
public function __construct(CD $cd) {
$this->_cd = $cd;
}
public function makeCaps() {
foreach ($this->_cd->trackList as & $track) {
$track = strtoupper($track);
}
}
}
$myCD = new CD();
foreach ($tracksFroExternalSource as $track) {
$myCD->addTrack($track);
}
//新增以下代码实现输出参数采用大写形式
$myCDCaps = new CDTrackListDecoratorCaps($myCD);
$myCDCaps->makeCaps();
print "The CD contains:{$myCD->getTrackList()}\n";
/* End of Decorator.class.php */
/* Location the file Design/Decorator.class.php */
<?php
/**
* 转自 《PHP设计模式》 第七章: 委托模式
* 当一个对象包含复杂单独立的,必须基于判决执行的功能性的若干部分时,最佳的方法是适用基于委托设计模式的对象。
*
*/
/**
* 示例: Web站点具有创建MP3文件播放列表的功能, 也具有选择以 M3U 或 PLS 格式下载播放列表的功能。
*
* 以下代码示例展示常规与委托两种模式实现
*
*/
//常规实现
class Playlist {
private $_songs;
public function __construct() {
$this->_songs = array();
}
public function addSong($location, $title) {
$song = array("location" => $location, "title" => $title);
$this->_songs[] = $song;
}
public function getM3U() {
$m3u = "#EXTM3U\n\n";
foreach ($this->_songs as $song) {
$m3u .= "#EXTINF: -1, {$song['title']}\n";
$m3u .= "{$song['location']}\n";
}
return $m3u;
}
public function getPLS() {
$pls = "[playlist]]\nNumberOfEntries = ". count($this->_songs) . "\n\n";
foreach ($this->_songs as $songCount => $song) {
$counter = $songCount + 1;
$pls .= "File{$counter} = {$song['location']}\n";
$pls .= "Title{$counter} = {$song['title']}\n";
$pls .= "LengthP{$counter} = -1 \n\n";
}
return $pls;
}
}
$playlist = new Playlist();
$playlist->addSong("/home/aaron/music/brr.mp3", "Brr");
$playlist->addSong("/home/aaron/music/goodbye.mp3", "Goodbye");
$externalRetrievedType = "pls";
if ($externalRetrievedType == "pls") {
$playlistContent = $playlist->getPLS();
} else {
$playlistContent = $playlist->getM3U();
}
echo $playlistContent;
//委托模式实现
class newPlaylist {
private $_songs;
private $_tyepObject;
public function __construct($type) {
$this->_songs = array();
$object = "{$type}Playlist";
$this->_tyepObject = new $object;
}
public function addSong($location, $title) {
$song = array("location" => $location, "title" => $title);
$this->_songs[] = $song;
}
public function getPlaylist() {
$playlist = $this->_tyepObject->getPlaylist($this->_songs);
return $playlist;
}
}
class m3uPlaylist {
public function getPlaylist($songs) {
$m3u = "#EXTM3U\n\n";
foreach ($songs as $song) {
$m3u .= "#EXTINF: -1, {$song['title']}\n";
$m3u .= "{$song['location']}\n";
}
return $m3u;
}
}
class plsPlaylist {
public function getPlaylist($songs) {
$pls = "[playlist]]\nNumberOfEntries = ". count($songs) . "\n\n";
foreach ($songs as $songCount => $song) {
$counter = $songCount + 1;
$pls .= "File{$counter} = {$song['location']}\n";
$pls .= "Title{$counter} = {$song['title']}\n";
$pls .= "LengthP{$counter} = -1 \n\n";
}
return $pls;
}
}
$externalRetrievedType = "pls";
$playlist = new newPlaylist($externalRetrievedType);
$playlist->addSong("/home/aaron/music/brr.mp3", "Brr");
$playlist->addSong("/home/aaron/music/goodbye.mp3", "Goodbye");
$playlistContent = $playlist->getPlaylist();
echo $playlistContent;
/* End of Delegate.class.php */
/* Location the file Design/Delegate.class.php */
<?php
/**
* 转自 《PHP设计模式》 第八章: 外观模式
* 外观设计模式的目标是: 控制外部错综复杂的关系, 并且提供简单的接口以利用上述组件的能力。
* 为了隐藏复杂的,执行业务进程某个步骤所需的方法和逻辑组,就应当使用基于外观设计模式的类。
*
*/
/**
* 代码示例: 获取CD对象,对其所有属性应用大写形式,并且创建一个要提交给Web服务的,格式完整的XML文档。
*
*/
class CD {
public $tracks = array();
public $band = '';
public $title = '';
public function __construct($tracks, $band, $title) {
$this->tracks = $tracks;
$this->band = $band;
$this->title = $title;
}
}
class CDUpperCase {
public static function makeString(CD $cd, $type) {
$cd->$type = strtoupper($cd->$type);
}
public static function makeArray(CD $cd, $type) {
$cd->$type = array_map("strtoupper", $cd->$type);
}
}
class CDMakeXML {
public static function create(CD $cd) {
$doc = new DomDocument();
$root = $doc->createElement("CD");
$root = $doc->appendChild($root);
$title = $doc->createElement("TITLE", $cd->title);
$title = $root->appendChild($title);
$band = $doc->createElement("BAND", $cd->band);
$band = $root->appendChild($band);
$tracks = $doc->createElement("TRACKS");
$tracks = $root->appendChild($tracks);
foreach ($cd->tracks as $track) {
$track = $doc->createElement("TRACK", $track);
$track = $tracks->appendChild($track);
}
return $doc->saveXML();
}
}
class WebServiceFacade {
public static function makeXMLCall(CD $cd) {
CDUpperCase::makeString($cd, "title");
CDUpperCase::makeString($cd, "band");
CDUpperCase::makeArray($cd, "tracks");
$xml = CDMakeXML::create($cd);
return $xml;
}
}
$tracksFromExternalSource = array("What It Means", "Brr", "Goodbye");
$band = "Never Again";
$title = "Waster of a Rib";
$cd = new CD($tracksFromExternalSource, $band, $title);
$xml = WebServiceFacade::makeXMLCall($cd);
echo $xml;
/* End of Facade.class.php */
/* Location the file Design/Facade.class.php */
<?php
/**
* 转自 《PHP设计模式》 第九章: 工厂模式
* 工厂设计模式: 提供获取某个对象的新实例的一个接口, 同时使调用代码避免确定实际实例化基类的步骤
*
*/
//基础标准CD类
class CD {
public $tracks = array();
public $band = '';
public $title = '';
public function __construct() {}
public function setTitle($title) {
$this->title = $title;
}
public function setBand($band) {
$this->band = $band;
}
public function addTrack($track) {
$this->tracks[] = $track;
}
}
//增强型CD类, 与标准CD的唯一不同是写至CD的第一个track是数据track("DATA TRACK")
class enhadcedCD {
public $tracks = array();
public $band = '';
public $title = '';
public function __construct() {
$this->tracks = "DATA TRACK";
}
public function setTitle($title) {
$this->title = $title;
}
public function setBand($band) {
$this->band = $band;
}
public function addTrack($track) {
$this->tracks[] = $track;
}
}
//CD工厂类,实现对以上两个类具体实例化操作
class CDFactory {
public static function create($type) {
$class = strtolower($type) . "CD";
return new $class;
}
}
//实例操作
$type = "enhadced";
$cd = CDFactory::create($type);
$tracksFromExternalSource = array("What It Means", "Brr", "Goodbye");
$cd->setBand("Never Again");
$cd->setTitle("Waste of a Rib");
foreach ($tracksFromExternalSource as $track) {
$cd->addTrack($track);
}
/* End of Factory.class.php */
/* End of file Design/Factory.class.php */
<?php
/**
* 转自 《PHP设计模式》 第十章: 解释器模式
* 解释器: 解释器设计模式用于分析一个实体的关键元素,并且针对每个元素都提供自己的解释或相应的动作。
* 解释器设计模式最常用于PHP/HTML 模板系统。
*
*/
class User {
protected $_username = "";
public function __construct($username) {
$this->_username = $username;
}
public function getProfilePage() {
$profile = "<h2>I like Never Again ! </h2>";
$profile .= "I love all of their songs. My favorite CD: <br />";
$profile .= "{{myCD.getTitle}}!!";
return $profile;
}
}
class userCD {
protected $_user = NULL;
public function setUser(User $user) {
$this->_user = $user;
}
public function getTitle() {
$title = "Waste of a Rib";
return $title;
}
}
class userCDInterpreter {
protected $_user = NULL;
public function setUser(User $user) {
$this->_user = $user;
}
public function getInterpreted() {
$profile = $this->_user->getProfilePage();
if (preg_match_all('/\{\{myCD\.(.*?)\}\}/', $profile, $triggers, PREG_SET_ORDER)) {
$replacements = array();
foreach ($triggers as $trigger) {
$replacements[] = $trigger[1];
}
$replacements = array_unique($replacements);
$myCD = new userCD();
$myCD->setUser($this->_user);
foreach ($replacements as $replacement) {
$profile = str_replace("{{myCD.{$replacement}}}", call_user_func(array($myCD, $replacement)), $profile);
}
}
return $profile;
}
}
$username = "aaron";
$user = new User($username);
$interpreter = new userCDInterpreter();
$interpreter->setUser($user);
print "<h1>{$username}'s Profile</h1>";
print $interpreter->getInterpreted();
/* End of Interpreter.class.php */
/* Location the file Design/Interpreter.class.php */
<?php
/**
* 转自 《PHP设计模式》 第十一章: 迭代器模式
* 迭代器:迭代器设计模式可帮助构造特定对象, 那些对象能够提供单一标准接口循环或迭代任何类型的可计数数据。
* 处理需要遍历的可计数数据时, 最佳的解决办法是创建一个基于迭代器设计模式的对象。
*
*/
class CD {
public $band = "";
public $title = "";
public $trackList = array();
public function __construct($band, $title) {
$this->band = $band;
$this->title = $title;
}
public function addTrack($track) {
$this->trackList[] = $track;
}
}
class CDSearchByBandIterator implements Iterator {
private $_CDs = array();
private $_valid = FALSE;
public function __construct($bandName) {
$db = mysql_connect("localhost", "root", "root");
mysql_select_db("test");
$sql = "select CD.id, CD.band, CD.title, tracks.tracknum, tracks.title as tracktitle ";
$sql .= "from CD left join tracks on CD.id = tracks.cid ";
$sql .= "where band = '" . mysql_real_escape_string($bandName) . "' ";
$sql .= "order by tracks.tracknum";
$results = mysql_query($sql);
$cdID = 0;
$cd = NULL;
while ($result = mysql_fetch_array($results)) {
if ($result["id"] !== $cdID) {
if ( ! is_null($cd)) {
$this->_CDs[] = $cd;
}
$cdID = $result['id'];
$cd = new CD($result['band'], $result['title']);
}
$cd->addTrack($result['tracktitle']);
}
$this->_CDs[] = $cd;
}
public function next() {
$this->_valid = (next($this->_CDs) === FALSE) ? FALSE : TRUE;
}
public function rewind() {
$this->_valid = (reset($this->_CDs) === FALSE) ? FALSE : TRUE;
}
public function valid() {
return $this->_valid;
}
public function current() {
return current($this->_CDs);
}
public function key() {
return key($this->_CDs);
}
}
$queryItem = "Never Again";
$cds = new CDSearchByBandIterator($queryItem);
print "<h1>Found the Following CDs</h1>";
print "<table border='1'><tr><th>Band</th><th>Ttile</th><th>Num Tracks</th></tr>";
foreach ($cds as $cd) {
print "<tr><td>{$cd->band}</td><td>{$cd->title}</td><td>";
print count($cd->trackList). "</td></tr>";
}
print "</table>";
/* End of Iterator.class.php */
/* Location the file Design/Iterator.class.php */
/*
SQLyog 企业版 - MySQL GUI v8.14
MySQL - 5.1.52-community : Database - test
*********************************************************************
*/
/*!40101 SET NAMES utf8 */;
/*!40101 SET SQL_MODE=''*/;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
/*Table structure for table `cd` */
DROP TABLE IF EXISTS `CD`;
CREATE TABLE `CD` (
`id` int(8) NOT NULL AUTO_INCREMENT,
`band` varchar(500) COLLATE latin1_bin NOT NULL DEFAULT '',
`title` varchar(500) COLLATE latin1_bin NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1 COLLATE=latin1_bin;
/*Data for the table `cd` */
insert into `CD`(`id`,`band`,`title`) values (1,'Never Again','Waster of a Rib');
/*Table structure for table `tracks` */
DROP TABLE IF EXISTS `tracks`;
CREATE TABLE `tracks` (
`cid` int(8) DEFAULT NULL,
`tracknum` int(8) DEFAULT NULL,
`title` varchar(500) COLLATE latin1_bin NOT NULL DEFAULT ''
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin;
/*Data for the table `tracks` */
insert into `tracks`(`cid`,`tracknum`,`title`) values (1,3,'What It Means'),(1,3,'Brr'),(1,3,'Goodbye');
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
<?php
/**
* 转自 《PHP设计模式》 第十二章: 中介者模式
* 中介者: 中介者设计莫用于开发一个对象,这个对象能够在类似对象相互之间不直接交互的情况下传送或调节对这些对象的集合的修改
* 处理具有类似属性并且属性需要保持同步的非耦合对象时,最佳的做法是使用基于中介者设计模式的对象。
*
*/
/**
* 测试用例描述:示例代码不仅允许乐队进入和管理他们的音乐合集,而且还允许乐队更新他们的配置文件,修改乐队相关信息以及更新其CD信息
* 现在,艺术家可上传MP3集合并从Web站点撤下CD。 因此, Web站点需要保持相对应的CD和MP3彼此同步。
*
*/
//CD类
class CD {
public $band = '';
public $title = '';
protected $_mediator;
public function __construct(MusicContainerMediator $mediator = NULL) {
$this->_mediator = $mediator;
}
public function save() {
//具体实现待定
var_dump($this);
}
public function changeBandName($bandname) {
if ( ! is_null($this->_mediator)) {
$this->_mediator->change($this, array("band" => $bandname));
}
$this->band = $bandname;
$this->save();
}
}
//MP3Archive类
class MP3Archive {
protected $_mediator;
public function __construct(MusicContainerMediator $mediator = NULL) {
$this->_mediator = $mediator;
}
public function save() {
//具体实现待定
var_dump($this);
}
public function changeBandName($bandname) {
if ( ! is_null($this->_mediator)) {
$this->_mediator->change($this, array("band" => $bandname));
}
$this->band = $bandname;
$this->save();
}
}
//中介者类
class MusicContainerMediator {
protected $_containers = array();
public function __construct() {
$this->_containers[] = "CD";
$this->_containers[] = "MP3Archive";
}
public function change($originalObject, $newValue) {
$title = $originalObject->title;
$band = $originalObject->band;
foreach ($this->_containers as $container) {
if ( ! ($originalObject instanceof $container)) {
$object = new $container;
$object->title = $title;
$object->band = $band;
foreach ($newValue as $key => $val) {
$object->$key = $val;
}
$object->save();
}
}
}
}
//测试实例
$titleFromDB = "Waste of a Rib";
$bandFromDB = "Never Again";
$mediator = new MusicContainerMediator();
$cd = new CD($mediator);
$cd->title = $titleFromDB;
$cd->band = $bandFromDB;
$cd->changeBandName("Maybe Once More");
/* End of Mediator.class.php */
/* Location the file Design/Mediator.class.php */