最近一直很低迷,总感觉这学期什么都没干,什么都没学。
为了证明我还是学了点什么的,所以要写这篇博客。
这学期看了三本书
第一本: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()); ?>