時(shí)間:2023-05-29 01:18:01 | 來源:網(wǎng)站運(yùn)營(yíng)
時(shí)間:2023-05-29 01:18:01 來源:網(wǎng)站運(yùn)營(yíng)
PHP開發(fā)自己的框架,這些知識(shí)點(diǎn)不能錯(cuò)過:一、PHP常用的四種數(shù)據(jù)結(jié)構(gòu)<?php //spl(php標(biāo)準(zhǔn)庫)數(shù)據(jù)結(jié)構(gòu) /** * 棧(先進(jìn)后出) */$stack = new SplStack();$stack->push('data1');//入棧(先進(jìn)后出)$stack->push('data2');//入棧$stack->push('data3');//入棧 echo $stack->pop();//出棧echo $stack->pop();//出棧echo $stack->pop();//出棧 /** *隊(duì)列(先進(jìn)先出) */$queue = new SplQueue();$queue->enqueue('data4');//入隊(duì)列$queue->enqueue('data5');//入隊(duì)列$queue->enqueue('data6');//入隊(duì)列 echo $queue->dequeue();//出隊(duì)列echo $queue->dequeue();//出隊(duì)列echo $queue->dequeue();//出隊(duì)列echo $queue->dequeue();//出隊(duì)列 /** * 堆 */$heap = new SplMinHeap();$heap->insert('data8');//入堆$heap->insert('data9');//入堆$heap->insert('data10');//入堆 echo $heap->extract();//從堆中提取數(shù)據(jù)echo $heap->extract();//從堆中提取數(shù)據(jù)echo $heap->extract();//從堆中提取數(shù)據(jù) /** * 固定數(shù)組(不論使不使用,都會(huì)分配相應(yīng)的內(nèi)存空間) */$array = new SplFixedArray(15);$array['0'] = 54;$array['6'] = 69;$array['10'] = 32;var_dump($array);
<?php/** * 框架入口文件 */define('BASEDIR',__DIR__);//項(xiàng)目根目錄include BASEDIR.'/Extend/Loader.php';//引入項(xiàng)目自動(dòng)加載類文件spl_autoload_register('//Extend//Loader::autoload');//執(zhí)行自動(dòng)加載函數(shù),完成類的自動(dòng)加載 $db = new /Extend/Database();$db->where('uid < 100000')->->order('uid desc')->limit(100);
2、自動(dòng)加載類 Loader.php<?phpnamespace Extend;/** * 實(shí)現(xiàn)框架的自動(dòng)加載 */class Loader{ /** * 實(shí)現(xiàn)文件的自動(dòng)載入 */ static function autoload($class) { require BASEDIR.'/'.str_replace('//','/',$class).'.php'; } }
3、數(shù)據(jù)庫類Database.php注:只是原理,并沒有對(duì)方法進(jìn)行具體的封裝,具體的封裝還是看個(gè)人喜好去定鏈?zhǔn)讲樵兊娘L(fēng)格。
<?phpnamespace Extend; class Database{ /** * 指定查詢條件 * @param $where */ function where($where) { return $this; } /** * 指定排序條件 */ function order($order) { return $this; } /** * 指定查詢的限制條數(shù) * @param $limit */ function limit($limit) { return $this; } }
其實(shí)就是對(duì)傳過來的條件進(jìn)行重新的底層封裝,然后再把當(dāng)前對(duì)象返回,使得可以不斷的鏈?zhǔn)讲樵儭?br><?php/** * 框架入口文件 */define('BASEDIR',__DIR__);//項(xiàng)目根目錄include BASEDIR.'/Extend/Loader.php';//引入項(xiàng)目自動(dòng)加載類文件spl_autoload_register('//Extend//Loader::autoload');//執(zhí)行自動(dòng)加載函數(shù),完成類的自動(dòng)加載 /** * 魔術(shù)方法的使用 */ # 實(shí)例化Object類$obj = new /Extend/Object();//當(dāng)前文件不存在這個(gè)類,就會(huì)自動(dòng)執(zhí)行自動(dòng)加載函數(shù)去包含相應(yīng)的類文件(即 Extend/Object.php) # __set 和 __get 對(duì)不存在的屬性進(jìn)行接管$obj->title = 'xiaobudiu'; //當(dāng)對(duì)一個(gè)不存在的類屬性賦值時(shí),會(huì)自動(dòng)調(diào)用類中定義的__set()echo $obj->title; //當(dāng)調(diào)用一個(gè)不存在的類屬性時(shí),會(huì)自動(dòng)調(diào)用類中定義的__get() # __call 和 __callStatic 對(duì)不存在或者權(quán)限不夠的類方法進(jìn)行接管$obj->getUserInfo('1000068'); //當(dāng)調(diào)用一個(gè)不存在的類方法時(shí),會(huì)調(diào)用__call(),并自動(dòng)將當(dāng)前方法名和參數(shù)傳到__call方法中/Extend/Object::getOpenId('1000068'); //當(dāng)調(diào)用一個(gè)不存在的類靜態(tài)方法時(shí),會(huì)調(diào)用__callStatic(),并自動(dòng)將當(dāng)前方法名和參數(shù)傳遞到__callStatic方法中 # echo或print對(duì)象時(shí),由__toString 接管echo $obj; //當(dāng)echo或print一個(gè)對(duì)象時(shí),會(huì)自動(dòng)調(diào)用類中定義的__toString方法 # 在php中,如果我們把一個(gè)對(duì)象當(dāng)成函數(shù)用,則由__invoke()接管$obj('xiaobudiu');//當(dāng)我們將一個(gè)對(duì)象當(dāng)成函數(shù)用的時(shí)候,會(huì)自動(dòng)調(diào)用當(dāng)前類中定義的__invoke()方法
2、 Extend/Object.php<?phpnamespace Extend;/** * 要求類名必須和文件名保持一致,即類名是Object,則所在文件名為Object.php * Class Object * @package Extend */class Object{ protected $array = array(); /** * 在代碼要給未定義的屬性賦值時(shí)調(diào)用,或在類外部修改被private修飾的類屬性時(shí)被調(diào)用 */ function __set($name, $value) { echo "this is __set func"; } /** * 當(dāng)在類外部訪問被private或proteced修飾的屬性或訪問一個(gè)類中原本不存在的屬性時(shí)被調(diào)用 * @param $name */ function __get($name) { echo "this is __get func"; } /** * 當(dāng)試圖調(diào)用不存在的方法或權(quán)限不足時(shí)會(huì)觸發(fā)__call() * @param $name 調(diào)用不存在的類方法時(shí)那個(gè)不存在的類方法的方法名 * @param $arguments 調(diào)用不存在的類方法時(shí)傳遞的參數(shù) */ function __call($name, $arguments) { var_dump($name,$arguments); } /** * 當(dāng)試圖調(diào)用不存在的靜態(tài)方法或權(quán)限不足時(shí)會(huì)觸發(fā)__callStatic() * @param $name 調(diào)用不存在的靜態(tài)方法時(shí)那個(gè)不存在的方法的方法名 * @param $arguments 調(diào)用不存在的靜態(tài)方法時(shí)傳遞的參數(shù) */ function __callStatic($name,$arguments) { var_dump($name,$arguments); } /** * 當(dāng)使用echo或print打印對(duì)象時(shí)會(huì)調(diào)用__toString()方法將對(duì)象轉(zhuǎn)化為字符串 */ function __toString() { echo "this is __toString func"; } /** * 對(duì)象本身不能直接當(dāng)函數(shù)用,如果被當(dāng)做函數(shù)用,會(huì)直接回調(diào)__invoke方法 * @param $param */ function __invoke($param) { echo $param."<br>this is __invoke func"; } }
<?php/** * 框架入口文件 */define('BASEDIR',__DIR__);//項(xiàng)目根目錄include BASEDIR.'/Extend/Loader.php';//引入項(xiàng)目自動(dòng)加載類文件spl_autoload_register('//Extend//Loader::autoload');//執(zhí)行自動(dòng)加載函數(shù),完成類的自動(dòng)加載 //構(gòu)造實(shí)例化緩存類時(shí)傳入的參數(shù)$config = array( 'host' => '127.0.0.1', 'pass' => 'myRedis&&&');//工廠模式創(chuàng)建cache對(duì)象$cache = Extend/CacheFactory::getCacheObj('redis',$config);var_dump($cache);
Extend/CacheFactory.php<?phpnamespace Extend; class CacheFactory{ const FILE = 1; const MEMCACHE = 2; const REDIS = 3; static $instance;//定義靜態(tài)屬性,用于存儲(chǔ)對(duì)象 /** * 工廠類創(chuàng)建緩存對(duì)象 * @param $type 指定緩存類型 * @param array $options 傳入緩存參數(shù) * @return FileCache|Memcache|RedisCache */ static function getCacheObj($type, array $options) { switch ($type) { case 'file': case self::FILE: self::$instance = new FileCache($options); break; case 'memcache': case self::MEMCACHE: self::$instance = new Memcache($options); break; case 'redis': case self::REDIS: self::$instance = new RedisCache($options); break; default: self::$instance = new FileCache($options); break; } return self::$instance; }}
2、單例模式<?php/** * 框架入口文件 */define('BASEDIR',__DIR__);//項(xiàng)目根目錄include BASEDIR.'/Extend/Loader.php';//引入項(xiàng)目自動(dòng)加載類文件spl_autoload_register('//Extend//Loader::autoload');//執(zhí)行自動(dòng)加載函數(shù),完成類的自動(dòng)加載 //單例模式創(chuàng)建對(duì)象$obj = Extend/SingleObject::getInstance();$obj2 = Extend/SingleObject::getInstance();var_dump($obj,$obj2);//從結(jié)果可以看出,兩個(gè)實(shí)例化的對(duì)象其實(shí)是一個(gè)對(duì)象
Extend/SingleObject.php<?phpnamespace Extend; /** * 單例模式創(chuàng)建唯一類對(duì)象 * Class SingleObject * @package Extend */class SingleObject{ //私有的靜態(tài)屬性,用于存儲(chǔ)類對(duì)象 private static $instance = null; //私有的構(gòu)造方法,保證不允許在類外 new private function __construct(){} //私有的克隆方法, 確保不允許通過在類外 clone 來創(chuàng)建新對(duì)象 private function __clone(){} //公有的靜態(tài)方法,用來實(shí)例化唯一當(dāng)前類對(duì)象 public static function getInstance() { if(is_null(self::$instance)){ self::$instance = new self; } return self::$instance; } }
3、注冊(cè)樹模式<?phpnamespace Extend; /** * 注冊(cè)樹模式 * Class RegisterTree * @package Extend */class RegisterTree{ static protected $objects;//靜態(tài)類屬性,用于儲(chǔ)存注冊(cè)到注冊(cè)樹上的對(duì)象 /** * 將對(duì)象注冊(cè)到注冊(cè)樹上 * @param $alias 對(duì)象的別名 * @param $object 對(duì)象 */ static function setObject($alias,$object) { self::$objects[$alias] = $object; } /** * 從注冊(cè)樹上取出給定別名相應(yīng)的對(duì)象 * @param $alias 將對(duì)象插入到注冊(cè)樹上時(shí)寫的別名 * @return mixed 對(duì)象 */ static protected function getObject($alias) { return self::$objects[$alias]; } /** * 將對(duì)象從注冊(cè)樹上刪除 * @param $alias 將對(duì)象插入到注冊(cè)樹上時(shí)寫的別名 */ public function unsetObject($alias) { unset(self::$objects[$alias]); } }
<?phpnamespace Extend; /** * 對(duì)象適配器模式具體流程 * 1、根據(jù)需求定義接口,進(jìn)而滿足新需求功能 * 2、定義新類,繼承并實(shí)現(xiàn)定義的接口 * 3、在實(shí)現(xiàn)接口時(shí),原有的功能,只通過原有類對(duì)象調(diào)用原有類功能(委托) * 4、再根據(jù)需求,在新類中實(shí)現(xiàn)新需求功能 * 【適用性】 * (1)你想使用一個(gè)已經(jīng)存在的類,而它的接口不符合你的需求 * (2)你想創(chuàng)建一個(gè)可以復(fù)用的類,該類可以與其他不相關(guān)的類或不可預(yù)見的類協(xié)同工作 * (3)你想使用一個(gè)已經(jīng)存在的子類,但是不可能對(duì)每一個(gè)都進(jìn)行子類化以匹配它們的接口。對(duì)象適配器可以適配它的父類接口(僅限于對(duì) */ /** * 目標(biāo)角色(根據(jù)需求定義含有舊功能加上新功能的接口) * Interface Target 我們期望得到的功能類 * @package Extend */interface Target{ public function simpleMethod1(); public function simpleMethod2();} /** * 源角色(在新功能提出之前的舊功能類和方法) * Class Adaptee * @package Extend */class Adaptee{ public function simpleMethod1() { echo 'Adapter simpleMethod1'."<br>"; } } /** * 類適配器角色(新定義接口的具體實(shí)現(xiàn)) * Class Adapter * @package Extend */class Adapter implements Target{ private $adaptee; function __construct() { //適配器初始化直接new 原功能類,以方便之后委派 $adaptee = new Adaptee(); $this->adaptee = $adaptee; } //委派調(diào)用Adaptee的sampleMethod1方法 public function simpleMethod1() { echo $this->adaptee->simpleMethod1(); } public function simpleMethod2() { echo 'Adapter simpleMethod2'."<br>"; } } /** * 客戶端調(diào)用 */$adapter = new Adapter();$adapter->simpleMethod1();$adapter->simpleMethod2();
2、策略模式<?php /** * 框架入口文件 */define('BASEDIR',__DIR__);//項(xiàng)目根目錄include BASEDIR.'/Extend/Loader.php';//引入項(xiàng)目自動(dòng)加載類文件spl_autoload_register('//Extend//Loader::autoload');//執(zhí)行自動(dòng)加載函數(shù),完成類的自動(dòng)加載 /** * 首頁數(shù)據(jù)控制器 * Class Index */class Home{ /** * 最好寫上這個(gè)注釋,告訴phpstorm是對(duì)應(yīng)的哪個(gè)接口類,否則雖然程序執(zhí)行正確,但phpstorm識(shí)別不了 * @var /Extend/UserType */ protected $userType; /** * 首頁展示數(shù)據(jù) * 使用策略模式 * Index constructor. */ function index() { echo "AD:"; $this->userType->showAd(); echo "Category:"; $this->userType->showCategory(); } /** * 策略模式 * 根據(jù)傳遞的用戶性別展示不同類別數(shù)據(jù) * @param /Extend/UserType $userType */ function setUserType(/Extend/UserType $userType) { $this->userType = $userType; } } $obj = new Home();if ($_GET['userType'] == 'female'){ $userType = new /Extend/FemaleUserType();} else { $userType = new /Extend/MaleUserType();}$obj->setUserType($userType);$obj->index();
Extend/userType.php(定義的接口)<?php namespace Extend; /** * 策略模式 * 定義根據(jù)性別不同展示不同商品類目和廣告接口 * Interface UserType * @package Extend */interface UserType{ //顯示廣告 function showAd(); //展示類目 function showCategory(); }
MaleUserType.php、FemaleUserType.php(具體實(shí)現(xiàn)的類 )<?php namespace Extend; /** * 定義男性商品類目和廣告位數(shù)據(jù)接口 * Class MaleUserType * @package Extend */class MaleUserType implements UserType{ /** * 廣告欄數(shù)據(jù)展示 */ function showAd() { echo "this is 男性’s 廣告條目數(shù)據(jù)"; } /** * 商品類目數(shù)據(jù)展示 */ function showCategory() { echo "this is 男性’s 商品類目數(shù)據(jù)"; } }<?php namespace Extend; /** * 定義女性商品類目和廣告位數(shù)據(jù)接口 * Class FemaleUserType * @package Extend */class FemaleUserType implements UserType{ /** * 廣告欄數(shù)據(jù)展示 */ function showAd() { echo "this is 女性’s 廣告條目數(shù)據(jù)"; } /** * 商品類目數(shù)據(jù)展示 */ function showCategory() { echo "this is 女性’s 商品類目數(shù)據(jù)"; } }
顯示效果:<?php/** * 框架入口文件 */define('BASEDIR',__DIR__);//項(xiàng)目根目錄include BASEDIR.'/Extend/Loader.php';//引入項(xiàng)目自動(dòng)加載類文件spl_autoload_register('//Extend//Loader::autoload');//執(zhí)行自動(dòng)加載函數(shù),完成類的自動(dòng)加載 //使用數(shù)據(jù)對(duì)象映射模式代替寫sql$user = new Extend/User(25);$user->name = '小卜丟飯團(tuán)子';$user->salary = '20000';$user->city = '浙江省';
Extend/User.php<?php namespace Extend; class User{ //對(duì)應(yīng)數(shù)據(jù)庫中的4個(gè)字段 public $id; public $name; public $salary; public $city; //存儲(chǔ)數(shù)據(jù)庫連接對(duì)象屬性 protected $pdo; public $data; function __construct($id) { $this->id = $id; $this->pdo = new /PDO('mysql:host=127.0.0.1;dbname=test','root','123456'); } function __destruct() { $this->pdo->query("update user set name = '{$this->name}',salary = '{$this->salary}',city = '{$this->city}' where id='{$this->id}'"); }}
這樣,執(zhí)行index.php文件,數(shù)據(jù)庫就會(huì)發(fā)生相應(yīng)的操作,也就實(shí)現(xiàn)了基本的數(shù)據(jù)對(duì)象映射。<?php /** * 框架入口文件 */define('BASEDIR',__DIR__);//項(xiàng)目根目錄include BASEDIR.'/Extend/Loader.php';//引入項(xiàng)目自動(dòng)加載類文件spl_autoload_register('//Extend//Loader::autoload');//執(zhí)行自動(dòng)加載函數(shù),完成類的自動(dòng)加載 class EX{ function index() { //使用數(shù)據(jù)對(duì)象映射模式代替寫sql $user = Extend/Factory::getUserObj(25); $user->name = '小卜丟飯團(tuán)子'; $user->salary = '20000'; $user->city = '浙江省'; } function test() { $user = Extend/Factory::getUserObj(25); $user->city = '廣東省'; } } $ex = new EX();$ex->index();
Extend/Factory.php<?php namespace Extend; class Factory{ /** * 工廠模式創(chuàng)建數(shù)據(jù)庫對(duì)象,單例模式保證創(chuàng)建唯一db對(duì)象 * @return mixed */ static function CreateDatabaseObj() { $db = Database::getInstance(); return $db; } /** * 工廠模式創(chuàng)建user對(duì)象,注冊(cè)樹模式保證創(chuàng)建唯一對(duì)象,避免資源浪費(fèi) * @param $id * @return User|mixed */ static function getUserObj($id) { $key = 'user'.$id; $user = RegisterTree::getObject($key); if (!$user) { $user = new User($id); RegisterTree::setObject($key,$user); } return $user; }}
Extend/Register.php<?php namespace Extend; /** * 注冊(cè)樹模式 * Class RegisterTree * @package Extend */class RegisterTree{ static protected $objects;//靜態(tài)類屬性,用于儲(chǔ)存注冊(cè)到注冊(cè)樹上的對(duì)象 /** * 將對(duì)象注冊(cè)到注冊(cè)樹上 * @param $alias 對(duì)象的別名 * @param $object 對(duì)象 */ static function setObject($alias,$object) { self::$objects[$alias] = $object; } /** * 從注冊(cè)樹上取出給定別名相應(yīng)的對(duì)象 * @param $alias 將對(duì)象插入到注冊(cè)樹上時(shí)寫的別名 * @return mixed 對(duì)象 */ static function getObject($alias) { return self::$objects[$alias]; } /** * 將對(duì)象從注冊(cè)樹上刪除 * @param $alias 將對(duì)象插入到注冊(cè)樹上時(shí)寫的別名 */ public function unsetObject($alias) { unset(self::$objects[$alias]); } }
Extend/User.php<?php namespace Extend; class User{ //對(duì)應(yīng)數(shù)據(jù)庫中的4個(gè)字段 public $id; public $name; public $salary; public $city; //存儲(chǔ)數(shù)據(jù)庫連接對(duì)象屬性 protected $pdo; public $data; function __construct($id) { $this->id = $id; $this->pdo = new /PDO('mysql:host=127.0.0.1;dbname=test','root','123456'); } function __destruct() { $this->pdo->query("update user set name = '{$this->name}',salary = '{$this->salary}',city = '{$this->city}' where id='{$this->id}'"); }}
這樣,就實(shí)現(xiàn)了稍復(fù)雜的數(shù)據(jù)對(duì)象映射模式和工廠模式、注冊(cè)樹模式相結(jié)合的案例。<?php/** * 框架入口文件 */define('BASEDIR',__DIR__);//項(xiàng)目根目錄include BASEDIR.'/Extend/Loader.php';//引入項(xiàng)目自動(dòng)加載類文件spl_autoload_register('//Extend//Loader::autoload');//執(zhí)行自動(dòng)加載函數(shù),完成類的自動(dòng)加載/** * 一個(gè)事件的邏輯控制器 * Class Event */class Event{ /** * 用戶確認(rèn)訂單 */ function firmOrder() { //這里假設(shè)一個(gè)事件發(fā)生了,比如用戶已經(jīng)完成下單 echo "用戶已下單<br>"; //傳統(tǒng)方式是在發(fā)生一個(gè)事件之后直接進(jìn)行一系列的相關(guān)處理,耦合度比較高,比如寫入日志,給用戶發(fā)郵件等等 echo "在用戶下單之后進(jìn)行的一系列操作<br>"; }}$event = new Event();$event->firmOrder();
4.2、觀察者模式典型實(shí)現(xiàn)方式:<?php/** * 觀察者模式場(chǎng)景描述: * 1、購票后記錄文本日志 * 2、購票后記錄數(shù)據(jù)庫日志 * 3、購票后發(fā)送短信 * 4、購票送抵扣卷、兌換卷、積分 * 5、其他各類活動(dòng)等 */ /** * 觀察者接口 */interface TicketObserver{ function buyTicketOver($sender, $args); //得到通知后調(diào)用的方法} /** * 被觀察者接口(購票主題接口) */interface TicketObserved{ function addObserver($observer); //提供注冊(cè)觀察者方法} /** * 主體邏輯,繼承被觀察者接口 * Class BuyTicket */class BuyTicket implements TicketObserved{ /** * 定義觀察者數(shù)組屬性,用于儲(chǔ)存觀察者 * @var array */ private $observers = array(); /** * 實(shí)現(xiàn)被觀察者接口定義的方法(添加觀察者) * @param $observer 實(shí)例化后的觀察者對(duì)象 */ public function addObserver($observer) { $this->observers[] = $observer; } /** * 購票主體方法 * BuyTicket constructor. * @param $ticket 購票排號(hào) */ public function buyTicket($ticket) { //1、根據(jù)需求寫購票邏輯 //.............. //2、購票成功之后,循環(huán)通知觀察者,并調(diào)用其buyTicketOver實(shí)現(xiàn)不同業(yè)務(wù)邏輯 foreach ($this->observers as $observe) { $observe->buyTicketOver($this, $ticket); //$this 可用來獲取主題類句柄,在通知中使用 } } } /** * 購票成功后,發(fā)送短信通知 * Class buyTicketMSN */class buyTicketMSN implements TicketObserver{ public function buyTicketOver($sender, $ticket) { echo (date ( 'Y-m-d H:i:s' ) . " 短信日志記錄:購票成功:$ticket<br>"); }} /** * 購票成功后,記錄日志 * Class buyTicketLog */class buyTicketLog implements TicketObserver{ public function buyTicketOver($sender, $ticket) { echo (date ( 'Y-m-d H:i:s' ) . " 文本日志記錄:購票成功:$ticket<br>"); }} /** * 購票成功后,贈(zèng)送優(yōu)惠券 * Class buyTicketCoupon */class buyTicketCoupon implements TicketObserver{ public function buyTicketOver($sender, $ticket) { echo (date ( 'Y-m-d H:i:s' ) . " 贈(zèng)送優(yōu)惠券:購票成功:$ticket 贈(zèng)送10元優(yōu)惠券1張。<br>"); }} //實(shí)例化購票類$buy = new BuyTicket();//添加多個(gè)觀察者$buy->addObserver(new buyTicketMSN());$buy->addObserver(new buyTicketLog());$buy->addObserver(new buyTicketCoupon());//開始購票$buy->buyTicket ("7排8號(hào)");
瀏覽器顯示結(jié)果:<?php/** * 抽象原型角色 */interface Prototype{ public function copy();} /** * 具體原型角色 */class ConcretePrototype implements Prototype{ private $_name; public function __construct($name) { $this->_name = $name; } public function setName($name) { $this->_name = $name; } public function getName() { return $this->_name; } public function copy() { //深拷貝實(shí)現(xiàn) //$serialize_obj = serialize($this); // 序列化 //$clone_obj = unserialize($serialize_obj); // 反序列化 //return $clone_obj; // 淺拷貝實(shí)現(xiàn) return clone $this; } } /** * 測(cè)試深拷貝用的引用類 */class Demo{ public $array;} //測(cè)試$demo = new Demo();$demo->array = array(1, 2);$object1 = new ConcretePrototype($demo);$object2 = $object1->copy(); var_dump($object1->getName());echo '<br />';var_dump($object2->getName());echo '<br />'; $demo->array = array(3, 4);var_dump($object1->getName());echo '<br />';var_dump($object2->getName());echo '<br />';
瀏覽器顯示結(jié)果:<?php/** * 裝飾器流程 * 1、聲明裝飾器接口(裝飾器接口) * 2、具體類繼承并實(shí)現(xiàn)裝飾器接口(顏色裝飾器實(shí)現(xiàn),字體大小裝飾器實(shí)現(xiàn)) * 3、在被裝飾者類中定義"添加裝飾器"方法(EchoText類中的addDecorator方法) * 4、在被裝飾者類中定義調(diào)用裝飾器的方法(EchoText類中的beforeEcho和afterEcho方法) * 5、使用時(shí),實(shí)例化被裝飾者類,并傳入裝飾器對(duì)象(比如new ColorDecorator('yellow')) */ /** * 裝飾器接口 * Class Decorator */interface Decorator{ public function beforeEcho(); public function afterEcho();} /** * 顏色裝飾器實(shí)現(xiàn) * Class ColorDecorator */class ColorDecorator implements Decorator{ protected $color; public function __construct($color) { $this->color = $color; } public function beforeEcho() { echo "<dis style='color: {$this->color}'>"; } public function afterEcho() { echo "</p>"; }} /** * 字體大小裝飾器實(shí)現(xiàn) * Class SizeDecorator */class SizeDecorator implements Decorator{ protected $size; public function __construct($size) { $this->size = $size; } public function beforeEcho() { echo "<dis style='font-size: {$this->size}px'>"; } public function afterEcho() { echo "</p>"; }} /** * 被裝飾者 * 輸出一個(gè)字符串 * 裝飾器動(dòng)態(tài)添加功能 * Class EchoText */class EchoText{ protected $decorators = array();//存放裝飾器 //裝飾方法 public function Index() { //調(diào)用裝飾器前置操作 $this->beforeEcho(); echo "你好,我是裝飾器。"; //調(diào)用裝飾器后置操作 $this->afterEcho(); } //添加裝飾器 public function addDecorator(Decorator $decorator) { $this->decorators[] = $decorator; } //執(zhí)行裝飾器前置操作 先進(jìn)先出原則 protected function beforeEcho() { foreach ($this->decorators as $decorator) $decorator->beforeEcho(); } //執(zhí)行裝飾器后置操作 先進(jìn)后出原則 protected function afterEcho() { $tmp = array_reverse($this->decorators); foreach ($tmp as $decorator) $decorator->afterEcho(); }} //實(shí)例化輸出類$echo = new EchoText();//增加裝飾器$echo->addDecorator(new ColorDecorator('yellow'));//增加裝飾器$echo->addDecorator(new SizeDecorator('22'));//輸出$echo->Index();
7、迭代器模式<?php/** * 框架入口文件 */define('BASEDIR',__DIR__);//項(xiàng)目根目錄include BASEDIR.'/Extend/Loader.php';//引入項(xiàng)目自動(dòng)加載類文件spl_autoload_register('//Extend//Loader::autoload');//執(zhí)行自動(dòng)加載函數(shù),完成類的自動(dòng)加載 $users = new Extend/AllUser();//循環(huán)遍歷出所有用戶數(shù)據(jù)foreach ($users as $user) { var_dump($user);}
Extend/AllUser.php<?phpnamespace Extend; /** * 迭代器模式,繼承php內(nèi)部自帶的迭代器接口(/Iterator) * Class AllUser * @package Extend */class AllUser implements /Iterator{ protected $index = 0;//表示索引 protected $ids = array();//用于儲(chǔ)存所有user的id(實(shí)際應(yīng)用中,可以采用注冊(cè)樹模式進(jìn)行存儲(chǔ)) protected $pdo;//用于存儲(chǔ)數(shù)據(jù)庫對(duì)象 function __construct() { //獲取pdo數(shù)據(jù)庫對(duì)象 $this->pdo = new /PDO('mysql:host=127.0.0.1;dbname=test','root','123456'); //獲取所有用戶的id $this->ids = $this->pdo->query("select id from user")->fetchAll(2); } /** * 實(shí)現(xiàn)接口方法,重置迭代器,回到集合開頭 */ public function rewind() { $this->index = 0; } /** * 實(shí)現(xiàn)接口方法,獲取當(dāng)前元素 * @return mixed|void */ public function current() { $id = $this->ids[$this->index]['id']; //獲取當(dāng)前用戶的數(shù)據(jù) $user_data = $this->pdo->query("select * from user where id='{$id}'")->fetch(2); return $user_data; } /** * 實(shí)現(xiàn)接口方法,獲取當(dāng)前元素鍵值 * @return mixed|void */ public function key() { return $this->index; } /** * 實(shí)現(xiàn)接口方法,獲取下一個(gè)元素 */ public function next() { $this->index++; } /** * 實(shí)現(xiàn)接口方法,驗(yàn)證是否還有下一個(gè)元素 * @return bool|void */ public function valid() { return $this->index < count($this->ids); } }
8、代理模式<?php/** * 框架入口文件 */define('BASEDIR',__DIR__);//項(xiàng)目根目錄include BASEDIR.'/Extend/Loader.php';//引入項(xiàng)目自動(dòng)加載類文件spl_autoload_register('//Extend//Loader::autoload');//執(zhí)行自動(dòng)加載函數(shù),完成類的自動(dòng)加載 // 1、傳統(tǒng)編程模式是手動(dòng)選擇#查詢操作使用從庫//$db_slave = Extend/Factory::getDatabase('slave');//$info = $db_slave->query("select * from user where id = 1 limit 1");#增刪改操作使用主庫//$db_master = Extend/Factory::getDatabase('master');//$db_master->query("update user name = 'xiaobudiu' where id = 29 limit 1"); // 2、使用代理模式$db_proxy = new Extend/Proxy();$db_proxy->getUserName(1);$db_proxy->setUserName(29,'xiaobudiu');
Extend/Proxy.php<?phpnamespace Extend; class Proxy implements IUserProxy{ function getUserName($id) { $db = Factory::getDatabase('slave'); $db->query("select name from user where id =$id limit 1"); } function setUserName($id, $name) { $db = Factory::getDatabase('master'); $db->query("update user set name = $name where id =$id limit 1"); }}
Extend/Factory.php<?phpnamespace Extend; class Factory{ static function getDatabase($id) { $key = 'database_'.$id; if ($id == 'slave') { $slaves = Application::getInstance()->config['database']['slave']; $db_conf = $slaves[array_rand($slaves)]; } else { $db_conf = Application::getInstance()->config['database'][$id]; } //注冊(cè)樹模式存儲(chǔ)及獲取對(duì)象 $db = Register::get($key); if (!$db) { $db = new Database/MySQLi(); $db->connect($db_conf['host'], $db_conf['user'], $db_conf['password'], $db_conf['dbname']); Register::set($key, $db); } return $db; } }
Extend/Application.php<?phpnamespace Extend; class Application{ public $base_dir; protected static $instance; public $config; protected function __construct($base_dir) { $this->base_dir = $base_dir; $this->config = new Config($base_dir.'/configs'); } static function getInstance($base_dir = '') { if (empty(self::$instance)) { self::$instance = new self($base_dir); } return self::$instance; } }
Extend/Config.php<?phpnamespace Extend; /** * 配置類,繼承于php自帶的ArrayAccess接口 * 允許一個(gè)對(duì)象以數(shù)組的方式訪問 * Class Config * @package Extend */class Config implements /ArrayAccess{ protected $path; protected $configs = array(); function __construct($path) { $this->path = $path; } function offsetGet($key) { if (empty($this->configs[$key])) { $file_path = $this->path.'/'.$key.'.php'; $config = require $file_path; $this->configs[$key] = $config; } return $this->configs[$key]; } function offsetSet($key, $value) { throw new /Exception("cannot write config file."); } function offsetExists($key) { return isset($this->configs[$key]); } function offsetUnset($key) { unset($this->configs[$key]); }}
configs/database.php<?php$config = array( 'master' => array( 'type' => 'MySQL', 'host' => '127.0.0.1', 'user' => 'root', 'password' => '123456', 'dbname' => 'test', ), 'slave' => array( 'slave1' => array( 'type' => 'MySQL', 'host' => '127.0.0.1', 'user' => 'root', 'password' => '123456', 'dbname' => 'test', ), 'slave2' => array( 'type' => 'MySQL', 'host' => '127.0.0.1', 'user' => 'root', 'password' => '123456', 'dbname' => 'test', ), ),);return $config;
以上內(nèi)容希望幫助到大家,很多PHPer在進(jìn)階的時(shí)候總會(huì)遇到一些問題和瓶頸,業(yè)務(wù)代碼寫多了沒有方向感,不知道該從那里入手去提升,對(duì)此我整理了一些資料,包括但不限于:分布式架構(gòu)、高可擴(kuò)展、高性能、高并發(fā)、服務(wù)器性能調(diào)優(yōu)、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql優(yōu)化、shell腳本、Docker、微服務(wù)、Nginx等多個(gè)知識(shí)點(diǎn)高級(jí)進(jìn)階干貨需要的可以免費(fèi)分享給大家,需要的戳此處進(jìn)階PHP月薪30k>>>架構(gòu)師成長(zhǎng)路線【視頻、面試文檔免費(fèi)獲取】關(guān)鍵詞:知識(shí),錯(cuò)過
客戶&案例
營(yíng)銷資訊
關(guān)于我們
客戶&案例
營(yíng)銷資訊
關(guān)于我們
微信公眾號(hào)
版權(quán)所有? 億企邦 1997-2025 保留一切法律許可權(quán)利。