PHP設計模式
自動加載
__autoload();
魔術方法,當加載不存在的類的時候會使用這個方法,每一個文件中只能存在一次,並且拋出的Exception是不可catch的。php
spl_autoload_register();
能夠調用用戶本身的ClassLoader, Composer就是使用這種方法實現類的自動加載mysql
每一個文件中可有多個spl_autoload_register();方法,調用更加靈活;sql
拋出的Exception能夠catch;數據庫
並且可使用 spl_autoload_unregister();進行自動加載關閉,節省內存空間.canvas
PSR-0規範
PSR-0 (Autoloading Standard) 自動加載標準設計模式
PSR-1 (Basic Coding Standard) 基礎編碼標準數組
PSR-2 (Coding Style Guide) 編碼風格嚮導瀏覽器
PSR-3 (Logger Interface) 日誌接口緩存
PSR-4 (Improved Autoloading) 自動加載的加強版,能夠替換掉PSR-0了。服務器
一個徹底合格的namespace和class必須符合這樣的結構:「\< Vendor Name>(< Namespace>)*< Class Name>」
每一個namespace必須有一個頂層的namespace(」Vendor Name」提供者名字)
每一個namespace能夠有多個子namespace
當從文件系統中加載時,每一個namespace的分隔符(/)要轉換成 DIRECTORY_SEPARATOR(操做系統路徑分隔符)
在類名中,每一個下劃線(_)符號要轉換成DIRECTORY_SEPARATOR(操做系統路徑分隔符)。在namespace中,下劃線(_)符號是沒有(特殊)意義的。
當從文件系統中載入時,合格的namespace和class必定是以 .php 結尾的
verdor name,namespaces,class名能夠由大小寫字母組合而成(大小寫敏感的)
PSR-4 規範
廢除了支持PHP5.3代碼之前的規範,而且去掉的下劃線的意義。
八個經常使用設計模式
單例模式 Eg。數據庫鏈接
要求:
-
$_instance必須爲靜態私有變量
-
構造函數 析構函數 拷貝函數必須爲私有 防止外界實例化對象
-
getInstance()方法必須公有,返回實例一個引用。
節省內存 避免頻繁new
工廠模式:生產對象使用
工廠模式能夠避免類更名字以後,其餘生成對象的代碼都要一一修改,使用工廠能夠避免頻繁修改。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
|
Test1.php <?php class Test1{ static function test(){ echo __FILE__; } }
Factory.php <?php class Factory{ /* * 若是某個類在不少的文件中都new ClassName(),那麼萬一這個類的名字 * 發生變動或者參數發生變化,若是不使用工廠模式,就須要修改每個PHP * 代碼,使用了工廠模式以後,只須要修改工廠類或者方法就能夠了。 */ static function createDatabase(){ $test = new Test1(); return $test; } }
Test.php <?php spl_autoload_register('autoload1');
$test = Factory::createDatabase(); $test->test(); function autoload1($class){ $dir = __DIR__; $requireFile = $dir."\\".$class.".php"; require $requireFile; }
|
註冊模式:解決全局局部共享對象使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
<?php
class Register { protected static $objects; function set($alias,$object)//將對象註冊到全局的樹上 { self::$objects[$alias]=$object;//將對象放到樹上 } static function get($name){ return self::$objects[$name];//獲取某個註冊到樹上的對象 } function _unset($alias) { unset(self::$objects[$alias]);//移除某個註冊到樹上的對象。 } }
|
適配器模式,相似於下面的決策模式
將各類不一樣的操做封裝成接口API 好比數據庫操做有MySQL,MySQLi,PDO。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
|
接口 IDatabase <?php namespace IMooc; interface IDatabase { function connect($host, $user, $passwd, $dbname); function query($sql); function close(); }
MySQL <?php namespace IMooc\Database; use IMooc\IDatabase; class MySQL implements IDatabase { protected $conn; function connect($host, $user, $passwd, $dbname) { $conn = mysql_connect($host, $user, $passwd); mysql_select_db($dbname, $conn); $this->conn = $conn; }
function query($sql) { $res = mysql_query($sql, $this->conn); return $res; }
function close() { mysql_close($this->conn); } }
MySQLi <?php namespace IMooc\Database; use IMooc\IDatabase; class MySQLi implements IDatabase { protected $conn;
function connect($host, $user, $passwd, $dbname) { $conn = mysqli_connect($host, $user, $passwd, $dbname); $this->conn = $conn; }
function query($sql) { return mysqli_query($this->conn, $sql); }
function close() { mysqli_close($this->conn); } }
|
策略模式:IOC思想 DI實現
也就是控制反轉 依賴注入
防止種類過多時候發生太多if致使代碼維護艱難
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
|
UserStrategy.php <?php /* * 聲明策略文件的接口,約定策略包含的行爲。 */ interface UserStrategy { function showAd(); function showCategory(); }
MaleUser.php <?php require_once 'Loader.php'; class MaleUser implements UserStrategy { function showAd(){ echo "IPhone6s"; } function showCategory(){ echo "電子產品"; } }
Page.php//執行文件 <?php require_once 'Loader.php'; class Page { protected $strategy; function index(){ echo "AD"; $this->strategy->showAd(); echo "<br>"; echo "Category"; $this->strategy->showCategory(); echo "<br>"; } function setStrategy(UserStrategy $strategy){ $this->strategy=$strategy; } }
$page = new Page(); if(isset($_GET['male'])){ $strategy = new MaleUser(); }else { $strategy = new FemaleUser(); } $page->setStrategy($strategy); $page->index();
|
觀察者模式
適用於一帶多頻繁更新的操做,好比業務邏輯中一個數據更改致使其餘表的數據也要跟着更改,直接硬編碼更改的操做的不太好的,並且後期的維護也很不利,使用觀察者模式能夠進行事件發佈,而後進行foreach進行更新操做。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
|
EventGenerator.php <?php require_once 'Loader.php'; abstract class EventGenerator{ private $observers = array(); function addObserver(Observer $observer){ $this->observers[]=$observer; } function notify(){ foreach ($this->observers as $observer){ $observer->update(); } } }
Observer.php <?php require_once 'Loader.php'; interface Observer{ function update();//這裏就是在事件發生後要執行的邏輯 }
//一個實現了EventGenerator抽象類的類,用於具體定義某個發生的事件 require 'Loader.php'; class Event extends EventGenerator{ function triger(){ echo "Event<br>"; } } class Observer1 implements Observer{ function update(){ echo "邏輯1<br>"; } } class Observer2 implements Observer{ function update(){ echo "邏輯2<br>"; } } $event = new Event(); $event->addObserver(new Observer1()); $event->addObserver(new Observer2()); $event->triger(); $event->notify();
|
原型模式
和工廠模式相似,適合建立大對象的時候,能夠節約一下內存開銷
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
Index.php <?php require 'Loader.php'; $c = new Canvas(); $c->init(); / $canvas1 = new Canvas(); // $canvas1->init(); $canvas1 = clone $c;//經過克隆,能夠省去init()方法,這個方法循環兩百次 //去產生一個數組。當項目中須要產生不少的這樣的對象時,就會new不少的對象,那樣 //是很是消耗性能的。 $canvas1->rect(2, 2, 8, 8); $canvas1->draw(); echo "-----------------------------------------<br>"; // $canvas2 = new Canvas(); // $canvas2->init(); $canvas2 = clone $c; $canvas2->rect(1, 4, 8, 8); $canvas2->draw();
|
MySQL 性能索引
索引數據結構
- B+ Tree
key放在葉子節點內的節點,葉子節點存放value 這樣能夠保證放更多的key,減小樹的高度,樹的高度的減小致使磁盤IO減小,能夠優化性能。葉子節點處有相互連接的指針。InnoDB採用B+Tree能夠將隨機IO轉換爲順序IO來提高效率。
- 搜索樹
父節點大於左孩子節點,右孩子節點大於父節點
- 平衡二叉樹
二叉樹,可是要求任意一個節點的左右孩子節點高度差不大於1
- Hash Struct
哈希結構僅能知足 Exist In 等查詢,不能使用範圍查詢。沒法進行排序查詢。不支持部分索引
彙集索引和非彙集索引
彙集索引Primary
InnoDB的數據文件自己就是索引文件,B+Tree的葉子節點上的data就是數據自己,key爲主鍵,這是聚簇索引
非聚簇索引,葉子節點上的data是主鍵(因此聚簇索引的key,不能過長)。
索引的優勢
-
變隨機IO爲順序IO
-
避免全表掃描
-
能夠幫助服務器避免排序或者臨時表
索引對中小型表會比較高效,大型表須要考慮一下分區。
索引的建立方法
1 2 3 4 5 6 7 8
|
create index `idx_img` on newuser(`img`);
alter table newuser add index `idx_extra_img` (`isDeleted`, `img`)
drop index `idx_img` on newuser;
// 強制走索引的方式 select * from newuser force index where xxxx;
|
索引的注意
-
不鼓勵使用like 不能夠所有模糊查詢 能夠 55kai% 這樣查
-
不能夠進行列上操做 好比count sum等都會全表掃描 性能不好
-
不適用Not in <> 操做。
-
儘量使用分解關聯查詢 這樣分解後 sql簡單,利於MySQL緩存、減小鎖競爭 更好的擴展和維護性。
HTTP 超文本傳輸協議
協議格式
三部分:
請求起始行、消息頭、消息體
分塊傳送
當瀏覽器想服務器請求一個資源,這個資源是一個動態資源,服務器沒法預知資源的大小,就應該採用分塊傳送
服務器先生成一個thunk 發送這個chunk 再生成 在發送 直到發送完成。
分塊發送須要在請求頭增長一個transfer-encoding:thunked
持久連接
HTTP早期版本由於連接不可複用,性能不好,TCP1.5的RTT(三次握手)和慢啓動會拖慢速度。
1.1版本引入keep-alive的connection頭,若是服務器和客戶端都肯定keep-alive的話,在一個TCP上面能夠傳送多個請求。
持久連接也不該該一直保持,每一個人都會佔用服務器資源,若是PV過高,服務器資源也會jinzhang
應該配置KeepAliveTimeout和KeepAliveRequests兩個參數 限時限量
PipeLine管線化
也就是一個TCP上面能夠產送多個HTTP請求,可是請求的順序必須和返回的順序一致
無狀態性
指的是協議層無狀態性 兩次請求並無任何關係。經過會話控制能夠保證訪問的狀態。