最近一直很低迷,总感觉这学期什么都没干,什么都没学。
为了证明我还是学了点什么的,所以要写这篇博客。
这学期看了三本书
第一本:php设计模式
本书讲了php当中的17种设计模式,现以代码形式总结如下。
1)适配器模式:
<?php
//原始错误提示类
class errorObject{
private $__error;
public function __construct($error){
$this->__error=$error;
}
public function getError(){
return $this->__error;
}
}
//新的调用方式
class logToCSV{
const CSV_LOCATION='log.csv';
private $__errorObject;
public function __construct($errorObject){
$__errorObject=$errorObject;
}
public function write(){
$line=$this->__errorObject->getErrorNumber();
$line.=',';
$line.=$this->__errorObject->getErrorText();
$line.='\n';
file_put_contents(self::CSV_LOCATION,$line,FILE_APPEND);
}
}
//需要设计适配器,使新的调用可以使用于原始的类
class logToCSVAdapter extends errorObject{
private $__errorNumber,$__errorText;
public function __construct($error){
parent::__construct($error);
$parts=explode(',',$this->getError());
$__errorNumber=$parts[0];
$__errorText=$parts[1];
}
public function getErrorNumber(){
return $this->__errorNumber;
}
public function getErrorNumber(){
return $this->__errorText;
}
}
?>
2)建造者模式:
<?php
class product{
protected $_type='';
protected $_size='';
protected $_color='';
public function setType1($type){
$this->_type=$type;
}
public function setSize($size){
$this->_size=$size;
}
public function setColor($color){
$this->_color=$color;
}
}
//为了创建完整的产品对象,需要将产品配置分别传递给产品类的每个方法
$productConfigs=array('type'=>'shirt','size'=>'XL','color'=>'red');
$product=new product();
$product->setType1($productConfigs['type']);
$product->setSize($productConfigs['size']);
$product->setColor($productConfigs['color']);
//创建对象时分别调用每个方法并不是最佳的做法,为此最好使用建造者模式
class productBuilder{
protected $_product=null;
protected $_configs=array();
public function __construct($configs){
$this->_product=new product();
$this->_configs=$configs;
}
public function build(){
$this->_product->setSize($this->_configs['size']);
$this->_product->setType1($this->_configs['type']);
$this->_product->setColor($this->_configs['color']);
}
public function getProduct(){
return $this->_product;
}
}
$build=new productBuilder($productConfigs);
$builder->build();
$product=$builder->getProduct();
//建造者设计模式的目的是消除其他对象的复杂创建过程。
?>
3)数据访问对象模式:
<?php
class model {
private $_connection;
function __construct() {
require_once ('../config/config.php');
$this->connect();
}
function connect() {
$this->_connection = @ mysql_connect(HOST, NAME, PASS) or die("数据库连接失败");
mysql_select_db(DATABASE, $this->_connection);
mysql_query("SET NAMES" . UT);
}
function fetch($value, $key = null) {
if (is_null($key)) {
$key = $this->_primaryKey;
}
$sql = "select * from {$this->_tableName} where {$key}='{$value}' ";
$result = mysql_query($sql, $this->_connection);
$row = array ();
while ($result = @ mysql_fetch_array($result)) {
$row[] = $result;
}
return $row;
}
function update($keyArray) {
$sql = " update {$this->_tableName} set ";
$updates = array ();
foreach ($keyArray as $column => $value) {
$updates[] = " {$column}='{$value}'";
}
$sql .= implode(',', $updates);
$sql .= " where {$this->_primaryKey}='{$keyArray[$this->_primaryKey]}'";
mysql_query($sql, $this->_connection);
}
}
class userDAO extends baseDAO
{
protected $_tableName='userTable';
protected $_primaryKey='id';
public function getUserByFirstName($name){
$result=$this->fetch($name,'firstName');
return $result;
}
}
?>
4)装饰者模式:
<?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;
}
}
//现在要将输出的音轨都编程大写字母,对于这么小的变化,
//最佳的做法并非修改基类或者创建父子关系,而是创建一个基于装饰者设计模式的对象。
class CDTrackListDecoratorCaps{
private $__cd;
public function __construct($cd){
$this->__cd=$cd;
}
public function makeCaps(){
foreach($this->__cd->trackList as & $track){
$track=strtoupper($track);
}
}
}
//只要在输出是装饰一下对象就可以
$strList=array('what is means','brr','goodbye');
$myCD=new CD();
foreach($strList as $track){
$myCD->addTrack($track);
}
$myCDCaps=new CDTrackListDecoratorCaps($myCD);
$myCDCaps->makeCaps();
print "The CD contains the following tracks :".$myCD->getTrackList();
?>
5 委托模式
<?php
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(){
$m3u="[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.="Length{$counter}=-1\n\n";
}
return $pls;
}
}
//编程时候可以使用委托设计模式来更改代码。这种做法的目的是消除潜在的难以控制的if/else语句。
//此外,随着添加更多的代码,最初的Playlist类会变得很庞大
class newPlaylist{
private $__songs;
private $__typeObject;
public function __construct($type){
$this->__songs=array();
$object="{$type}PlaylistDelegate";
$this->__typeObject=new $object;
}
public function addSong($location,$title){
$song=array('location'=>$location,'title'=>$title);
$this->__songs[]=$song;
}
public function getPlaylist(){
$playlist=$this->__typeObject->getPlaylist($this->__songs);
return $playlist;
}
}
//newPlaylist对象的构造函数现在接受$type参数。除了初始化内部的歌曲数组之外,构造函数还可以根据$type
//动态的创建指定委托的新实例并将该实例内部存储在$__typeObject变量中。
class m3uPlaylistDelegate{
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 plsPlaylistDelegate{
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.="Length{$counter}=-1\n\n";
}
return $pls;
}
}
//这样调用
$externalRetrievedType='pls';
$playlist=new newPlaylist($externalRetrievedType);
$playlist->addSong('local','title');
$playlist->addSong('local2','title2');
echo $playlistContent=$playlist->getPlaylist();
?>
6外观模式
<?php
class CD{
public $tracks=array();
public $band='';
public $title='';
public function __construct($title,$band,$tracks){
$this->title=$title;
$this->band=$band;
$this->tracks=$tracks;
}
}
$tracksFromExterlSource=array('What Is Means','Brrr','Boodbye');
$title='Waste of a Rib';
$band='Never Again';
$cd=new CD($title,$band,$tracksFromExterlSource);
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('1.0');
$root=$doc->createElement('CD');
$doc->appendChild($root);
$title=$doc->createElement('TITLE',$cd->title);
$doc->appendChild($title);
$band=$doc->createElement('BAND',$cd->band);
$doc->appendChild($band);
$tracks=$doc->createElement('TRACKS');
$doc->appendChild($tracks);
foreach($cd->tracks as $track){
$track=$doc->createElement('TRACK',$track);
$doc->appendChild($tracks);
}
return $doc->saveXML();
}
}
//乍看起来,编程人员可能希望通过下面的方式实现这样的功能:
/*CDUpperCase::makeString($cd,'title');
CDUpperCase::makeString($cd,'band');
CDUpperCase::makeArray($cd,'tracks');*/
//虽然这是解决问题的一种方式,但并不是最佳方式,我们应当针对具体的Web服务调用创建一个Facade对象。
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;
}
}
//这样前面列出的4行代码只需要替换为如下一行代码
print WebServiceFacade::makeXMLCall($cd);
?>
7原型模式:
<?php
class CD{
public $band='';
public $title='';
public $trackList=array();
public function __construct($id){
$handle=mysql_connect('localhost','user','pass');
mysql_select_db('CD',$handle);
$query="select band,title from cd where id={$id}";
$results=mysql_query($query,$handle);
if($row=mysql_fetch_assoc($results)){
$this->band=$row['band'];
$this->title=$row['title'];
}
mysql_free_result($results);
}
public function buy(){
var_dump($this);
}
}
class MixtapeCD extends CD{
public function __clone(){
$this->title='Mixtape';
}
}
$externalPurchaseInfoBandID=12;
$bandMixProto=new MixtapeCD($externalPurchaseInfoBandID);
$externalPurchaseInfo=array();
$externalPurchaseInfo[]=array('brrr','goodbye');
$externalPurchaseInfo[]=array('what is means','brrr');
foreach ($externalPurchaseInfo as $mixed){
$cd=clone $bandMixProto;
$cd->trackList=$mixed;
$cd->buy();
}
//处理创建成本较高和新实例的初始信息保持相对不变的对象时.
//最佳的做法是使用基于原型的设计模式创建的复制类。
?>
8 代理模式:
<?php
class CD{
protected $_title='';
protected $_band='';
protected $_handle=null;
public function __construct($title, $band){
$this->_title=$title;
$this->_band=$band;
}
public function buy(){
$this->_connect();
$query="update CDs set bought=1 where band=' ";
$query.=mysql_real_escape_string($this->_band,$this->_handle);
$query.="'and title'";
$query.=mysql_real_escape_string($this->_title,$this->_handle);
$query.="'";
mysql_query($query,$this->_handle);
}
protected function _connect(){
$this->_handle=mysql_connect('localhost','user','pass');
mysql_select_db('CD',$this->_handle);
}
}
class DallasNoCCDProxy extends CD{
protected function _connect(){
$this->_handle=mysql_connect('dallas','user','pass');
mysql_select_db('CD',$this->_handle);
}
}
$externalTitle='waste of a rib';
$externalBand='Never Again';
$cd=new DallasNoCCDProxy($externalTitle, $externalBand);
$cd->buy();
?>
9单元素模式:
<?php
class InventoryConnection{
protected static $_instance=null;
protected $_handle=null;
public static function getInstance(){
if(!self::$_instance instanceof self){
self::$_instance=new self;
}
return self::$_instance;
}
protected function __construct(){
$this->_handle=mysql_connect('localhost','user','pass');
mysql_select_db('CD',$this->_handle);
}
}
//调用时候
$inventory=InventoryConnection::getInstance();
//因为操作会发生多次,所以InventoryConnection对象最好是单元素对象。
//针对每个购买的CD都打开一个于数据库的连接并不是好的办法
//当某个对象的实例化在整个代码流中允许发生一次时,最佳的做法就是单元素设计模式。
?>
10策略模式:
<?php
class CDusesStrategy{
public $title='';
public $band='';
protected $_strategy;
public function __construct($title, $band){
$this->title=$title;
$this->band=$band;
}
public function setStrategyContext($strategyObject){
$this->_strategy=$strategyObject;
}
public function get(){
return $this->_strategy->get($this);
}
}
class CDAsXMLStrategy{
public function get(CDusesStrategy $cd){
$doc=new DomDocument('1.0');
$root=$doc->createElement('CD');
$doc->appendChild($root);
$title=$doc->createElement('TITLE',$cd->title);
$doc->appendChild($title);
$band=$doc->createElement('BAND',$cd->band);
$doc->appendChild($band);
return $doc->saveXML();
}
}
class CDAsJSONStrategy{
public function get(CDusesStrategy $cd){
$json=array();
$json['CD']['title']=$cd->title;
$json['CD']['band']=$cd->band;
return json_encode($json);
}
}
//调用时候
$cd=new CDusesStrategy($title,$band);
//xml output
$cd->setStragegyContext(new CDAsXMLStrategy);
print $cd->get();
//json output
$cd->setStragegyContext(new CDAsJSONStrategy);
print $cd->get();
//在能够创建应用于基对象的,由自包含算法组成的可交互对象时,最佳的做法就是使用策略模式。
?>
11工厂模式
<?php
class CD{
public $title='';
public $band='';
public $track=array();
}
class enhancedCD{
public $title='';
public $band='';
public $track=array();
}
class CDFactory{
public static function create($type){
$class=strtolower($type)."CD";
return new $class;
}
}
$type='enhanced';
$cd=CDFactory::create($type);
?>
12解释器模式
<?php
class User{
protected $_username='';
public function __construct($username){
$this->_username=$username;
}
public function getProfilePage(){
$profile="<h2>I like Never Again!";
$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){
$this->_user=$user;
}
public function getTitle(){
$title='Waste of a Rib';
return $title;
}
}
class userCDInterpreter{
protected $_user=null;
public function setUser($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();
?>
13迭代器模式:
<?php
class CD{
public $band='';
public $title='';
}
class CDDearchByBandIterator implements Iterator{
private $_CDs=array();
private $_valid=false;
public function __construct($bandName){
while($result=mysql_fetch_array($result)){
$cd=new CD();
$_CDs[]=$cd;
}
}
public function next(){
$this->_valid=(next($this->_CDs))?false:true;
}
public function rewind(){
$this->_valid=(reset($this->_CDs))?false:true;
}
public function valid(){
return $this->_valid;
}
public function current(){
return current($this->CDs);
}
public function key(){
return key($this->_CDs);
}
}
?>
14 中介者模式:
<?php
class CD{
public $band='';
public $title='';
protected $_mediator;
public function __construct($mediator=null){
$this->_mediator=$mediator;
}
public function save(){
var_dump($this);
}
public function changeBandName($newName){
if(!is_null($this->_mediator)){
$this->_mediator->change($this,array('band'=>$newName));
}
$this->band=$newName;
$this->save();
}
}
class MP3Archive{
public $band='';
public $title='';
protected $_mediator;
public function __construct($mediator=null){
$this->_mediator=$mediator;
}
public function save(){
var_dump($this);
}
public function changeBandName($newName){
if(!is_null($this->_mediator)){
$this->_mediator->change($this,array('band'=>$newName));
}
$this->band=$newName;
$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(!($changeObject instanceof $container)){
$object=new $container;
$object->title=$title;
$object->band=$band;
foreach($newValue as $key=>$val){
$object->$key=$val;
}
$object->save();
}
}
}
}
?>
15 模版模式:
<?php
abstract class SaleItemTemplate{
public $price=0;
public final function setPriceAdjustments(){
$this->price+=$this->taxAddition();
$this->price+=$this->oversizedAddition();
}
protected function oversizeAddition(){
return 0;
}
abstract protected function taxAddition();
}
class CD extends SaleItemTemplate{
public $band;
public $title;
public function __construct(){
}
protected function taxAddition(){
return round($this->price*.05,2);
}
}
class BandEndorsedCaseOfCereal extends SaleItemTemplate{
public $band;
public function __construct(){
}
protected function taxAddition(){
return 0;
}
protected function oversizedAddition(){
return round($this->price*.20,2);
}
}
?>
16 访问者模式:
<?php
class CD{
public $band;
public $title;
public $price;
public function __construct($band,$title,$price){
$this->band=$band;
$this->title=$title;
$this->price=$price;
}
public function buy(){
}
public function acceptVisitor(){
$visitor->visitCD($this);
}
}
class CDVisitorLogPurchase{
public function visitCD($CD){
$logline="{$cd->title}by{$cd->band}was purchased for{$cd->price}";
$logline.="at".date('r')."\n";
file_put_contents('/logs/purchases.log',$logline,FILE_APPEND);
}
}
$externalBand='Never Agin';
$externalTitle='Waste of a Rib';
$externalPrice=9.99;
$cd=new CD($externalBand,$externalTitle,$externalPrice);
$cd->buy();
$cd->acceptVisitor(new CDVisitorLogPurchase());
?>