本篇文章為大家展示了PHP的基礎(chǔ)知識點和基本用法,代碼簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細(xì)介紹希望你能有所收獲。
定制設(shè)計可以根據(jù)自己的需求進行定制,成都網(wǎng)站設(shè)計、網(wǎng)站建設(shè)構(gòu)思過程中功能建設(shè)理應(yīng)排到主要部位公司成都網(wǎng)站設(shè)計、網(wǎng)站建設(shè)的運用實際效果公司網(wǎng)站制作網(wǎng)站建立與制做的實際意義
簡介:spl是php的一個標(biāo)準(zhǔn)庫。
官方文檔:http://php.net/manual/zh/book.spl.php
<?php //spl(php標(biāo)準(zhǔn)庫)數(shù)據(jù)結(jié)構(gòu) /** * 棧(先進后出) */ $stack = new SplStack(); $stack->push('data1');//入棧(先進后出) $stack->push('data2');//入棧 $stack->push('data3');//入棧 echo $stack->pop();//出棧 echo $stack->pop();//出棧 echo $stack->pop();//出棧 /** *隊列(先進先出) */ $queue = new SplQueue(); $queue->enqueue('data4');//入隊列 $queue->enqueue('data5');//入隊列 $queue->enqueue('data6');//入隊列 echo $queue->dequeue();//出隊列 echo $queue->dequeue();//出隊列 echo $queue->dequeue();//出隊列 echo $queue->dequeue();//出隊列 /** * 堆 */ $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ù)組(不論使不使用,都會分配相應(yīng)的內(nèi)存空間) */ $array = new SplFixedArray(15); $array['0'] = 54; $array['6'] = 69; $array['10'] = 32; var_dump($array);
1、入口文件 index.php
<?php /** * 框架入口文件 */ define('BASEDIR',__DIR__);//項目根目錄 include BASEDIR.'/Extend/Loader.php';//引入項目自動加載類文件 spl_autoload_register('\\Extend\\Loader::autoload');//執(zhí)行自動加載函數(shù),完成類的自動加載 $db = new \Extend\Database(); $db->where('uid < 100000')->->order('uid desc')->limit(100);
2、自動加載類 Loader.php
<?php namespace Extend; /** * 實現(xiàn)框架的自動加載 */ class Loader { /** * 實現(xiàn)文件的自動載入 */ static function autoload($class) { require BASEDIR.'/'.str_replace('\\','/',$class).'.php'; } }
3、數(shù)據(jù)庫類Database.php
注:只是原理,并沒有對方法進行具體的封裝,具體的封裝還是看個人喜好去定鏈?zhǔn)讲樵兊娘L(fēng)格。
<?php namespace Extend; class Database { /** * 指定查詢條件 * @param $where */ function where($where) { return $this; } /** * 指定排序條件 */ function order($order) { return $this; } /** * 指定查詢的限制條數(shù) * @param $limit */ function limit($limit) { return $this; } }
其實就是對傳過來的條件進行重新的底層封裝,然后再把當(dāng)前對象返回,使得可以不斷的鏈?zhǔn)讲樵儭?/p>
在php設(shè)計模式中,會涉及到很多魔術(shù)方法的使用,這里也對經(jīng)常會用到的魔術(shù)方法進行簡單總結(jié)。
1、框架入口文件 index.php
<?php /** * 框架入口文件 */ define('BASEDIR',__DIR__);//項目根目錄 include BASEDIR.'/Extend/Loader.php';//引入項目自動加載類文件 spl_autoload_register('\\Extend\\Loader::autoload');//執(zhí)行自動加載函數(shù),完成類的自動加載 /** * 魔術(shù)方法的使用 */ # 實例化Object類 $obj = new \Extend\Object();//當(dāng)前文件不存在這個類,就會自動執(zhí)行自動加載函數(shù)去包含相應(yīng)的類文件(即 Extend/Object.php) # __set 和 __get 對不存在的屬性進行接管 $obj->title = 'xiaobudiu'; //當(dāng)對一個不存在的類屬性賦值時,會自動調(diào)用類中定義的__set() echo $obj->title; //當(dāng)調(diào)用一個不存在的類屬性時,會自動調(diào)用類中定義的__get() # __call 和 __callStatic 對不存在或者權(quán)限不夠的類方法進行接管 $obj->getUserInfo('1000068'); //當(dāng)調(diào)用一個不存在的類方法時,會調(diào)用__call(),并自動將當(dāng)前方法名和參數(shù)傳到__call方法中 \Extend\Object::getOpenId('1000068'); //當(dāng)調(diào)用一個不存在的類靜態(tài)方法時,會調(diào)用__callStatic(),并自動將當(dāng)前方法名和參數(shù)傳遞到__callStatic方法中 # echo或print對象時,由__toString 接管 echo $obj; //當(dāng)echo或print一個對象時,會自動調(diào)用類中定義的__toString方法 # 在php中,如果我們把一個對象當(dāng)成函數(shù)用,則由__invoke()接管 $obj('xiaobudiu');//當(dāng)我們將一個對象當(dāng)成函數(shù)用的時候,會自動調(diào)用當(dāng)前類中定義的__invoke()方法
2、 Extend/Object.php
<?php namespace Extend; /** * 要求類名必須和文件名保持一致,即類名是Object,則所在文件名為Object.php * Class Object * @package Extend */ class Object { protected $array = array(); /** * 在代碼要給未定義的屬性賦值時調(diào)用,或在類外部修改被private修飾的類屬性時被調(diào)用 */ function __set($name, $value) { echo "this is __set func"; } /** * 當(dāng)在類外部訪問被private或proteced修飾的屬性或訪問一個類中原本不存在的屬性時被調(diào)用 * @param $name */ function __get($name) { echo "this is __get func"; } /** * 當(dāng)試圖調(diào)用不存在的方法或權(quán)限不足時會觸發(fā)__call() * @param $name 調(diào)用不存在的類方法時那個不存在的類方法的方法名 * @param $arguments 調(diào)用不存在的類方法時傳遞的參數(shù) */ function __call($name, $arguments) { var_dump($name,$arguments); } /** * 當(dāng)試圖調(diào)用不存在的靜態(tài)方法或權(quán)限不足時會觸發(fā)__callStatic() * @param $name 調(diào)用不存在的靜態(tài)方法時那個不存在的方法的方法名 * @param $arguments 調(diào)用不存在的靜態(tài)方法時傳遞的參數(shù) */ function __callStatic($name,$arguments) { var_dump($name,$arguments); } /** * 當(dāng)使用echo或print打印對象時會調(diào)用__toString()方法將對象轉(zhuǎn)化為字符串 */ function __toString() { echo "this is __toString func"; } /** * 對象本身不能直接當(dāng)函數(shù)用,如果被當(dāng)做函數(shù)用,會直接回調(diào)__invoke方法 * @param $param */ function __invoke($param) { echo $param."<br>this is __invoke func"; } }
1、工廠模式
通過傳入?yún)?shù)的不同,來實例化不同的類。
index.php
<?php /** * 框架入口文件 */ define('BASEDIR',__DIR__);//項目根目錄 include BASEDIR.'/Extend/Loader.php';//引入項目自動加載類文件 spl_autoload_register('\\Extend\\Loader::autoload');//執(zhí)行自動加載函數(shù),完成類的自動加載 //構(gòu)造實例化緩存類時傳入的參數(shù) $config = array( 'host' => '127.0.0.1', 'pass' => 'myredis&&&' ); //工廠模式創(chuàng)建cache對象 $cache = Extend\CacheFactory::getCacheObj('redis',$config); var_dump($cache);
Extend/CacheFactory.php
<?php namespace Extend; class CacheFactory { const FILE = 1; const MEMCACHE = 2; const REDIS = 3; static $instance;//定義靜態(tài)屬性,用于存儲對象 /** * 工廠類創(chuàng)建緩存對象 * @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、單例模式
保證一個類只實例化一個類對象,進而減少系統(tǒng)開銷和資源的浪費
index.php
<?php /** * 框架入口文件 */ define('BASEDIR',__DIR__);//項目根目錄 include BASEDIR.'/Extend/Loader.php';//引入項目自動加載類文件 spl_autoload_register('\\Extend\\Loader::autoload');//執(zhí)行自動加載函數(shù),完成類的自動加載 //單例模式創(chuàng)建對象 $obj = Extend\SingleObject::getInstance(); $obj2 = Extend\SingleObject::getInstance(); var_dump($obj,$obj2);//從結(jié)果可以看出,兩個實例化的對象其實是一個對象
Extend/SingleObject.php
<?php namespace Extend; /** * 單例模式創(chuàng)建唯一類對象 * Class SingleObject * @package Extend */ class SingleObject { //私有的靜態(tài)屬性,用于存儲類對象 private static $instance = null; //私有的構(gòu)造方法,保證不允許在類外 new private function __construct(){} //私有的克隆方法, 確保不允許通過在類外 clone 來創(chuàng)建新對象 private function __clone(){} //公有的靜態(tài)方法,用來實例化唯一當(dāng)前類對象 public static function getInstance() { if(is_null(self::$instance)){ self::$instance = new self; } return self::$instance; } }
3、注冊樹模式
將我們用到的對象注冊到注冊樹上,然后在之后要用到這個對象的時候,直接從注冊樹上取下來就好。(就和我們用全局變量一樣方便)
Extend/RegisterTree,php
<?php namespace Extend; /** * 注冊樹模式 * Class RegisterTree * @package Extend */ class RegisterTree { static protected $objects;//靜態(tài)類屬性,用于儲存注冊到注冊樹上的對象 /** * 將對象注冊到注冊樹上 * @param $alias 對象的別名 * @param $object 對象 */ static function setObject($alias,$object) { self::$objects[$alias] = $object; } /** * 從注冊樹上取出給定別名相應(yīng)的對象 * @param $alias 將對象插入到注冊樹上時寫的別名 * @return mixed 對象 */ static protected function getObject($alias) { return self::$objects[$alias]; } /** * 將對象從注冊樹上刪除 * @param $alias 將對象插入到注冊樹上時寫的別名 */ public function unsetObject($alias) { unset(self::$objects[$alias]); } }
1、適配器模式
將一個類的接口轉(zhuǎn)換成客戶希望的另一個接口,適配器模式使得原本的由于接口不兼容而不能一起工作的那些類可以一起工作。
應(yīng)用場景:老代碼接口不適應(yīng)新的接口需求,或者代碼很多很亂不便于繼續(xù)修改,或者使用第三方類庫。
常見的有兩種適配器,分別是類適配器和對象適配器,這里拿更看好的對象適配器舉例:
<?php namespace Extend; /** * 對象適配器模式具體流程 * 1、根據(jù)需求定義接口,進而滿足新需求功能 * 2、定義新類,繼承并實現(xiàn)定義的接口 * 3、在實現(xiàn)接口時,原有的功能,只通過原有類對象調(diào)用原有類功能(委托) * 4、再根據(jù)需求,在新類中實現(xiàn)新需求功能 * 【適用性】 * (1)你想使用一個已經(jīng)存在的類,而它的接口不符合你的需求 * (2)你想創(chuàng)建一個可以復(fù)用的類,該類可以與其他不相關(guān)的類或不可預(yù)見的類協(xié)同工作 * (3)你想使用一個已經(jīng)存在的子類,但是不可能對每一個都進行子類化以匹配它們的接口。對象適配器可以適配它的父類接口(僅限于對 */ /** * 目標(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>"; } } /** * 類適配器角色(新定義接口的具體實現(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、策略模式
將一組特定的行為和算法封裝成類,以適應(yīng)某些特定的上下文環(huán)境,這種模式就是策略模式,策略模式可以實現(xiàn)依賴倒置以及控制反轉(zhuǎn)。
實例舉例:假如一個電商網(wǎng)站系統(tǒng),針對男性女性用戶要各自跳轉(zhuǎn)到不同的商品類目,并且所有的廣告位展示展示不同的廣告。
index.php
<?php /** * 框架入口文件 */ define('BASEDIR',__DIR__);//項目根目錄 include BASEDIR.'/Extend/Loader.php';//引入項目自動加載類文件 spl_autoload_register('\\Extend\\Loader::autoload');//執(zhí)行自動加載函數(shù),完成類的自動加載 /** * 首頁數(shù)據(jù)控制器 * Class Index */ class Home { /** * 最好寫上這個注釋,告訴phpstorm是對應(yīng)的哪個接口類,否則雖然程序執(zhí)行正確,但phpstorm識別不了 * @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(具體實現(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ù)"; } }
顯示效果:
3、數(shù)據(jù)對象映射模式
將對象和數(shù)據(jù)存儲映射起來,對一個對象的操作會映射為對數(shù)據(jù)存儲的操作。
下面在代碼中實現(xiàn)數(shù)據(jù)對象映射模式,我們將實現(xiàn)一個ORM類,將復(fù)雜的sql語句映射成對象屬性的操作。并結(jié)合使用數(shù)據(jù)對象映射模式、工廠模式、注冊模式。
-----(1)數(shù)據(jù)庫映射模式簡單實例實現(xiàn)
index.php
<?php /** * 框架入口文件 */ define('BASEDIR',__DIR__);//項目根目錄 include BASEDIR.'/Extend/Loader.php';//引入項目自動加載類文件 spl_autoload_register('\\Extend\\Loader::autoload');//執(zhí)行自動加載函數(shù),完成類的自動加載 //使用數(shù)據(jù)對象映射模式代替寫sql $user = new Extend\User(25); $user->name = '小卜丟飯團子'; $user->salary = '20000'; $user->city = '浙江省';
Extend/User.php
<?php namespace Extend; class User { //對應(yīng)數(shù)據(jù)庫中的4個字段 public $id; public $name; public $salary; public $city; //存儲數(shù)據(jù)庫連接對象屬性 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ù)庫就會發(fā)生相應(yīng)的操作,也就實現(xiàn)了基本的數(shù)據(jù)對象映射。
-------(2)數(shù)據(jù)庫映射模式復(fù)雜案例實現(xiàn)
index.php
<?php /** * 框架入口文件 */ define('BASEDIR',__DIR__);//項目根目錄 include BASEDIR.'/Extend/Loader.php';//引入項目自動加載類文件 spl_autoload_register('\\Extend\\Loader::autoload');//執(zhí)行自動加載函數(shù),完成類的自動加載 class EX { function index() { //使用數(shù)據(jù)對象映射模式代替寫sql $user = Extend\Factory::getUserObj(25); $user->name = '小卜丟飯團子'; $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ù)庫對象,單例模式保證創(chuàng)建唯一db對象 * @return mixed */ static function CreateDatabaseObj() { $db = Database::getInstance(); return $db; } /** * 工廠模式創(chuàng)建user對象,注冊樹模式保證創(chuàng)建唯一對象,避免資源浪費 * @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; /** * 注冊樹模式 * Class RegisterTree * @package Extend */ class RegisterTree { static protected $objects;//靜態(tài)類屬性,用于儲存注冊到注冊樹上的對象 /** * 將對象注冊到注冊樹上 * @param $alias 對象的別名 * @param $object 對象 */ static function setObject($alias,$object) { self::$objects[$alias] = $object; } /** * 從注冊樹上取出給定別名相應(yīng)的對象 * @param $alias 將對象插入到注冊樹上時寫的別名 * @return mixed 對象 */ static function getObject($alias) { return self::$objects[$alias]; } /** * 將對象從注冊樹上刪除 * @param $alias 將對象插入到注冊樹上時寫的別名 */ public function unsetObject($alias) { unset(self::$objects[$alias]); } }
Extend/User.php
<?php namespace Extend; class User { //對應(yīng)數(shù)據(jù)庫中的4個字段 public $id; public $name; public $salary; public $city; //存儲數(shù)據(jù)庫連接對象屬性 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}'"); } }
這樣,就實現(xiàn)了稍復(fù)雜的數(shù)據(jù)對象映射模式和工廠模式、注冊樹模式相結(jié)合的案例。
4、觀察者模式
當(dāng)一個對象狀態(tài)發(fā)生改變時,依賴它的對象會全部收到通知,并自動更新。
場景:一個事件發(fā)生后,要執(zhí)行一連串更新操作。傳統(tǒng)的編程方式就是在事件的代碼之后直接加入處理邏輯,當(dāng)更新的邏輯增多之后,代碼會變的難以維護。這種方式是耦合的,侵入式的,增加新的邏輯需要修改事件主體的代碼。觀察者模式實現(xiàn)了低耦合,非侵入式的通知與更新機制。
4.1、傳統(tǒng)模式舉例:
<?php /** * 框架入口文件 */ define('BASEDIR',__DIR__);//項目根目錄 include BASEDIR.'/Extend/Loader.php';//引入項目自動加載類文件 spl_autoload_register('\\Extend\\Loader::autoload');//執(zhí)行自動加載函數(shù),完成類的自動加載 /** * 一個事件的邏輯控制器 * Class Event */ class Event { /** * 用戶確認(rèn)訂單 */ function firmOrder() { //這里假設(shè)一個事件發(fā)生了,比如用戶已經(jīng)完成下單 echo "用戶已下單<br>"; //傳統(tǒng)方式是在發(fā)生一個事件之后直接進行一系列的相關(guān)處理,耦合度比較高,比如寫入日志,給用戶發(fā)郵件等等 echo "在用戶下單之后進行的一系列操作<br>"; } } $event = new Event(); $event->firmOrder();
4.2、觀察者模式典型實現(xiàn)方式:
(1)定義2個接口:觀察者(通知)接口、被觀察者(主題)接口
(2)定義2個類,觀察者類實現(xiàn)觀察者接口、被觀察者類實現(xiàn)被觀察者接口
(3)被觀察者注冊自己需要通知的觀察者
(4)被觀察者類某個業(yè)務(wù)邏輯發(fā)生時,通知觀察者對象,進而每個觀察者執(zhí)行自己的業(yè)務(wù)邏輯。
代碼示例:
test.php
<?php /** * 觀察者模式場景描述: * 1、購票后記錄文本日志 * 2、購票后記錄數(shù)據(jù)庫日志 * 3、購票后發(fā)送短信 * 4、購票送抵扣卷、兌換卷、積分 * 5、其他各類活動等 */ /** * 觀察者接口 */ interface TicketObserver { function buyTicketOver($sender, $args); //得到通知后調(diào)用的方法 } /** * 被觀察者接口(購票主題接口) */ interface TicketObserved { function addObserver($observer); //提供注冊觀察者方法 } /** * 主體邏輯,繼承被觀察者接口 * Class BuyTicket */ class BuyTicket implements TicketObserved { /** * 定義觀察者數(shù)組屬性,用于儲存觀察者 * @var array */ private $observers = array(); /** * 實現(xiàn)被觀察者接口定義的方法(添加觀察者) * @param $observer 實例化后的觀察者對象 */ public function addObserver($observer) { $this->observers[] = $observer; } /** * 購票主體方法 * BuyTicket constructor. * @param $ticket 購票排號 */ public function buyTicket($ticket) { //1、根據(jù)需求寫購票邏輯 //.............. //2、購票成功之后,循環(huán)通知觀察者,并調(diào)用其buyTicketOver實現(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>"); } } /** * 購票成功后,贈送優(yōu)惠券 * Class buyTicketCoupon */ class buyTicketCoupon implements TicketObserver { public function buyTicketOver($sender, $ticket) { echo (date ( 'Y-m-d H:i:s' ) . " 贈送優(yōu)惠券:購票成功:$ticket 贈送10元優(yōu)惠券1張。<br>"); } } //實例化購票類 $buy = new BuyTicket(); //添加多個觀察者 $buy->addObserver(new buyTicketMSN()); $buy->addObserver(new buyTicketLog()); $buy->addObserver(new buyTicketCoupon()); //開始購票 $buy->buyTicket ("7排8號");
瀏覽器顯示結(jié)果:
5、原型模式
原型模式與工廠模式的作用類似,都是用來創(chuàng)建對象的。但是實現(xiàn)方式是不同的。原型模式是先創(chuàng)建好一個原型對象,然后通過clone原型對象來創(chuàng)建新的對象。這樣,就免去了類創(chuàng)建時重復(fù)的初始化操作。
原型模式適用于大對象的創(chuàng)建,創(chuàng)建一個大對象需要很大的開銷,如果每次new就會消耗很大,原型模式僅需內(nèi)存拷貝即可。
代碼實例:
<?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() { //深拷貝實現(xiàn) //$serialize_obj = serialize($this); // 序列化 //$clone_obj = unserialize($serialize_obj); // 反序列化 //return $clone_obj; // 淺拷貝實現(xiàn) return clone $this; } } /** * 測試深拷貝用的引用類 */ class Demo { public $array; } //測試 $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é)果:
6、裝飾器模式
可以動態(tài)的添加或修改類的功能
一個類實現(xiàn)一個功能,如果要再修改或添加額外的功能,傳統(tǒng)的編程模式需要寫一個子類繼承它,并重新實現(xiàn)類的方法。
使用裝飾器模式,僅需在運行時添加一個裝飾器對象即可實現(xiàn),可以實現(xiàn)最大的靈活性。
<?php /** * 裝飾器流程 * 1、聲明裝飾器接口(裝飾器接口) * 2、具體類繼承并實現(xiàn)裝飾器接口(顏色裝飾器實現(xiàn),字體大小裝飾器實現(xiàn)) * 3、在被裝飾者類中定義"添加裝飾器"方法(EchoText類中的addDecorator方法) * 4、在被裝飾者類中定義調(diào)用裝飾器的方法(EchoText類中的beforeEcho和afterEcho方法) * 5、使用時,實例化被裝飾者類,并傳入裝飾器對象(比如new ColorDecorator('yellow')) */ /** * 裝飾器接口 * Class Decorator */ interface Decorator { public function beforeEcho(); public function afterEcho(); } /** * 顏色裝飾器實現(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>"; } } /** * 字體大小裝飾器實現(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>"; } } /** * 被裝飾者 * 輸出一個字符串 * 裝飾器動態(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í)行裝飾器前置操作 先進先出原則 protected function beforeEcho() { foreach ($this->decorators as $decorator) $decorator->beforeEcho(); } //執(zhí)行裝飾器后置操作 先進后出原則 protected function afterEcho() { $tmp = array_reverse($this->decorators); foreach ($tmp as $decorator) $decorator->afterEcho(); } } //實例化輸出類 $echo = new EchoText(); //增加裝飾器 $echo->addDecorator(new ColorDecorator('yellow')); //增加裝飾器 $echo->addDecorator(new SizeDecorator('22')); //輸出 $echo->Index();
7、迭代器模式
在不需要了解內(nèi)部實現(xiàn)的前提下,遍歷一個聚合對象的內(nèi)部元素而又不暴露該對象的內(nèi)部表示,這就是PHP迭代器模式的定義。
相對于傳統(tǒng)編程模式,迭代器模式可以隱藏遍歷元素的所需的操作。
index.php
<?php /** * 框架入口文件 */ define('BASEDIR',__DIR__);//項目根目錄 include BASEDIR.'/Extend/Loader.php';//引入項目自動加載類文件 spl_autoload_register('\\Extend\\Loader::autoload');//執(zhí)行自動加載函數(shù),完成類的自動加載 $users = new Extend\AllUser(); //循環(huán)遍歷出所有用戶數(shù)據(jù) foreach ($users as $user) { var_dump($user); }
Extend/AllUser.php
<?php namespace Extend; /** * 迭代器模式,繼承php內(nèi)部自帶的迭代器接口(\Iterator) * Class AllUser * @package Extend */ class AllUser implements \Iterator { protected $index = 0;//表示索引 protected $ids = array();//用于儲存所有user的id(實際應(yīng)用中,可以采用注冊樹模式進行存儲) protected $pdo;//用于存儲數(shù)據(jù)庫對象 function __construct() { //獲取pdo數(shù)據(jù)庫對象 $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); } /** * 實現(xiàn)接口方法,重置迭代器,回到集合開頭 */ public function rewind() { $this->index = 0; } /** * 實現(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; } /** * 實現(xiàn)接口方法,獲取當(dāng)前元素鍵值 * @return mixed|void */ public function key() { return $this->index; } /** * 實現(xiàn)接口方法,獲取下一個元素 */ public function next() { $this->index++; } /** * 實現(xiàn)接口方法,驗證是否還有下一個元素 * @return bool|void */ public function valid() { return $this->index < count($this->ids); } }
8、代理模式
在客戶端與實體之間建立一個代理對象(proxy),客戶端對實體進行操作全部委派給代理對象,隱藏實體的具體實現(xiàn)細(xì)節(jié)。
典型的應(yīng)用就是mysql的主從結(jié)構(gòu),讀寫分離。在mysql中,對所有讀的操作請求從庫,所有寫的操作請求主庫。
聲明一個代理類,前臺使用時只需創(chuàng)建一個代理類,調(diào)用對應(yīng)方法即可。代碼實例:
index.php
<?php /** * 框架入口文件 */ define('BASEDIR',__DIR__);//項目根目錄 include BASEDIR.'/Extend/Loader.php';//引入項目自動加載類文件 spl_autoload_register('\\Extend\\Loader::autoload');//執(zhí)行自動加載函數(shù),完成類的自動加載 // 1、傳統(tǒ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
<?php namespace 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
<?php namespace 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]; } //注冊樹模式存儲及獲取對象 $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
<?php namespace 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
<?php namespace Extend; /** * 配置類,繼承于php自帶的ArrayAccess接口 * 允許一個對象以數(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;
1、單一職責(zé)原則:一個類只需要做好一件事情。不要使用一個類完成很多功能,而應(yīng)該拆分成更多更小的類。
2、開放封閉原則:一個類寫好之后,應(yīng)該是可擴展而不可修改的。
3、依賴倒置原則:一個類不應(yīng)該強依賴另外一個類,每個類對于另外一個類都是可替換的。
4、配置化原則:盡量使用配置,而不是硬編碼。
5、面向接口編程原則:只需要關(guān)心某個類提供了哪些接口,而不需要關(guān)心他的實現(xiàn)。
1、php中使用ArrayAccess實現(xiàn)配置文件的加載(使得程序可以以數(shù)組的方式進行讀取配置)
(1)定義Config.php,繼承php自帶的ArrayAccess接口,并實現(xiàn)相應(yīng)的方法,用于讀取和設(shè)置配置
Extend/Config.php
<?php namespace Extend; /** * 配置類,繼承于php自帶的ArrayAccess接口 * 允許一個對象以數(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]); } }
(2)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;
(3)讀取配置
index.php
<?php /** * 框架入口文件 */ define('BASEDIR',__DIR__);//項目根目錄 include BASEDIR.'/Extend/Loader.php';//引入項目自動加載類文件 spl_autoload_register('\\Extend\\Loader::autoload');//執(zhí)行自動加載函數(shù),完成類的自動加載 $config = new Extend\Config(__DIR__.'/configs'); var_dump($config['database']);
(4)瀏覽器顯示:
到此,就可以在程序中隨心所欲的加載配置文件了。
2、在工廠方法中讀取配置,生成可配置化的對象
Extend/Factory.php
<?php namespace 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]; } //注冊樹模式存儲及獲取對象 $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
<?php namespace 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
<?php namespace Extend; /** * 配置類,繼承于php自帶的ArrayAccess接口 * 允許一個對象以數(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]); } }
上述內(nèi)容就是PHP的基礎(chǔ)知識點和基本用法,你們學(xué)到知識或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識儲備,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
當(dāng)前文章:PHP的基礎(chǔ)知識點和基本用法
文章來源:http://jinyejixie.com/article30/ijgppo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站改版、服務(wù)器托管、網(wǎng)站收錄、響應(yīng)式網(wǎng)站、標(biāo)簽優(yōu)化、商城網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)