3.25周 一週拾遺

PHP設計模式

自動加載

__autoload();

魔術方法,當加載不存在的類的時候會使用這個方法,每一個文件中只能存在一次,並且拋出的Exception是不可catch的。php

spl_autoload_register();

能夠調用用戶本身的ClassLoader, Composer就是使用這種方法實現類的自動加載mysql

每一個文件中可有多個spl_autoload_register();方法,調用更加靈活;sql

拋出的Exception能夠catch;數據庫

並且可使用 spl_autoload_unregister();進行自動加載關閉,節省內存空間.canvas

  • 自動加載不可用於CLI模式

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。數據庫鏈接

要求:

  1. $_instance必須爲靜態私有變量

  2. 構造函數 析構函數 拷貝函數必須爲私有 防止外界實例化對象

  3. 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 性能索引

索引數據結構

  1. B+ Tree

key放在葉子節點內的節點,葉子節點存放value 這樣能夠保證放更多的key,減小樹的高度,樹的高度的減小致使磁盤IO減小,能夠優化性能。葉子節點處有相互連接的指針。InnoDB採用B+Tree能夠將隨機IO轉換爲順序IO來提高效率。

  1. 搜索樹

父節點大於左孩子節點,右孩子節點大於父節點

  1. 平衡二叉樹

二叉樹,可是要求任意一個節點的左右孩子節點高度差不大於1

  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請求,可是請求的順序必須和返回的順序一致

無狀態性

指的是協議層無狀態性 兩次請求並無任何關係。經過會話控制能夠保證訪問的狀態。

相關文章
相關標籤/搜索