`

PHP设计模式

    博客分类:
  • PHP
 
阅读更多
<?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 */
 
分享到:
评论

相关推荐

    php设计模式

    因此,我会根据【标题】和【描述】字段中提供的信息,来生成关于PHP设计模式的知识点。 PHP设计模式的知识点主要包括: 1. 设计模式的概念:设计模式是软件开发中用于解决特定问题的一般性模板,它不是直接的代码...

    php设计模式介绍,php设计模式介绍

    **PHP设计模式详解** 在软件开发中,设计模式是一种经过时间考验、被广泛接受的解决方案模板,用于解决常见的设计问题。对于PHP开发者来说,理解并掌握设计模式是提升代码质量和可维护性的关键步骤。设计模式并非...

    php设计模式高清版

    ### PHP设计模式详解 #### 一、设计模式概述 **设计模式**是在软件工程领域中广泛应用的一种编程思想,它提供了一种系统化的解决方案,用于解决软件设计中的常见问题。设计模式不仅有助于提高代码的可复用性和可...

    php设计模式全解.rar

    《PHP设计模式全解》是一本深入探讨PHP编程中设计模式的资源集合,它旨在帮助PHP开发者提升代码质量、可维护性和复用性。设计模式是软件工程中的宝贵经验总结,通过将常见的问题解决方案标准化,使得开发过程更加...

    PHP设计模式介绍 中文chm版

    《PHP设计模式介绍》 英文原名:Guide.to.PHP.Design.Patterns 出版社:Marco Tabini & Associates, Inc. 作者:Jason E. Sweat 中文翻译:PHPChina 本书的目标 本书的目的不是为了全面的介绍各种类别的软件设计模式...

    php设计模式,一本详细介绍PHP设计模式的书

    PHP设计模式,适合有经验的开发人员 导言 当你在不断的试图从你的应用程序中发现新的特征时,你是否发现你提出的解决方法和一些 以前你已经实现的东西是如此的类似呢?如果你是一个程序员(即使你才 开始很短的时 间...

    Learning PHP设计模式

    **PHP设计模式详解** 在IT领域,设计模式是一种在特定情境下解决常见问题的标准方法,它们代表了软件设计中的最佳实践。PHP作为一种广泛使用的服务器端脚本语言,同样可以从设计模式中受益。《Learning PHP设计模式...

    learning php 设计模式 中文版 pdf

    《Learning PHP设计模式》这本书是面向PHP开发者的一本专业指南,旨在帮助读者深入理解并掌握设计模式在PHP编程中的应用。设计模式是软件工程中经过时间验证的最佳实践,它们为解决常见问题提供了一种标准的方法,使...

    PHP设计模式代码精解(视频源码)

    教程名称:PHP设计模式代码精解(视频 源码)课程目录:【】BroPHP框架(1.0)【】MVC模式中的单态和工厂 6-18 其他资料【】MVC模式中的单态和工厂 6-18 大纲【】MVC模式中的单态和工厂 6-18 课堂代码【】MVC模式中的...

    Learning PHP设计模式 ([美]William Sanders) 中文pdf扫描版

    《Learning PHP设计模式》是由美国作家William Sanders撰写的一本面向初学者和中级PHP开发者的设计模式指南。这本书旨在帮助读者理解并应用设计模式这一强大的软件工程工具,以提高PHP编程的效率和代码质量。设计...

    《Learning_PHP设计模式》PDF英文版本下载.txt

    根据提供的文件信息,本文将对《Learning_PHP设计模式》这一主题进行深入解析,重点围绕PHP设计模式的基础概念、分类及应用场景展开讨论。 ### PHP设计模式基础 #### 1. 设计模式简介 设计模式是在软件工程领域内...

    PHP设计模式.rar

    《PHP设计模式详解》 设计模式是软件工程中的一种最佳实践,它是在特定上下文中解决常见问题的经验总结。在PHP编程领域,理解并熟练运用设计模式对于提升代码质量、可维护性和可扩展性至关重要。本资料主要围绕PHP...

    《PHP设计模式指南》中文版.rar

    《PHP设计模式指南》的目的不是为了介绍一个全面的软件设计模式名录,也不是为了开发任何新的设计模式或术语,而是为了突出介绍一些已有的,知名的设计模式。值得一提的是,《PHP设计模式指南》介绍了那些我自认为对...

    php设计模式案例详解

    PHP设计模式是将这些模式应用到PHP编程中的具体实现,可以帮助开发者编写更灵活、可维护和高效的代码。以下是对标题和描述中提及的一些设计模式的详细说明: 1. **解释器设计模式**:它允许我们创建一个简单的语言...

    php设计模式demo

    PHP设计模式是将这些模式应用于PHP编程语言中的实践。本文将深入探讨PHP设计模式的几个重要方面,以及如何通过示例代码`demo0707`来理解它们。 一、单例模式(Singleton) 单例模式确保一个类只有一个实例,并提供...

    PHP设计模式 ((美)Aaron Saray) 中文pdf扫描版

    《PHP设计模式》一书由美国作者Aaron Saray撰写,主要针对PHP开发者,详细阐述了在实际编程过程中如何运用设计模式提升代码质量和可维护性。设计模式是软件工程中的最佳实践,它们是解决常见问题的经验总结,使得...

    php设计模式代码

    本压缩包“php设计模式代码”包含了作者亲笔编写的一些常见PHP设计模式的实现,下面将对这些设计模式进行详细的阐述。 1. **单例模式**:这种模式确保一个类只有一个实例,并提供一个全局访问点。在PHP中,单例模式...

    php设计模式介绍

    《PHP设计模式介绍》导言 《PHP设计模式介绍》第一章 编程惯用法 《PHP设计模式介绍》第二章 值对象模式 《PHP设计模式介绍》第三章 工厂模式 《PHP设计模式介绍》第四章 单条模式 《PHP设计模式介绍》第五章 ...

Global site tag (gtag.js) - Google Analytics