激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - PHP教程 - 自制PHP框架之設計模式

自制PHP框架之設計模式

2021-05-17 17:05編程老頭 PHP教程

本文是自制PHP框架的第三篇,我們主要來講解下PHP的設計模式的使用,本文我們一起來學習PHP中最常用的三種設計模式:單例設計模式、工廠設計模式和觀察者設計模式。

為什么要使用設計模式

設計模式,我的理解是為了達到“可復用”這個目標,而設計的一套相互協作的類。

感興趣的讀者可以閱讀《design patterns: elements of reusable object-oriented software》,四位作者(gang of four)在書中列舉了業界聞名的23種設計模式。

這里先介紹我們框架要涉及的三種設計模式。

單例模式(singleton)

單例模式可以保證一個類只有一個對象實例, 常用在數據庫存取類,從而節省硬件資源的消耗。

這里,我們改寫上一章節的mysql類

?
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
class mysql extends db{
    private static $instance=null;
    public static function getinstance(){
        if(self::$instance==null){
            self::$instance=new mysql();
        }
        return self::$instance;
    }
    public function mysql(){
        
        /*config*/
        $this->ip='*';
        $this->serverid='*';
        $this->serverpassword='*';
        $this->databasename='*';
        /*end of config*/
        
        $this->connection=mysqli_connect($this->ip,$this->serverid,$this->serverpassword,$this->databasename);
        
        if(!$this->connection){
            die('could not connect'.$this->connection);
        }
        
        mysqli_query($this->connection,'set names utf8');
    }
 
    public function execute($sql){
        return mysqli_query($this->connection,$sql);
    }
 
    public function query($sql){
        $result=mysqli_query($this->connection,$sql);
        $arr=array();
        while($row=mysqli_fetch_array($result)){
            $arr[]=$row;
        }
        return $arr;
    }
    public function close(){
        mysqli_close($this->connection);
    }
}

這里要注意的是,如果實例化一個mysql類,我們不再寫

?
1
$db=new mysql();

而是這樣:

?
1
$db=mysql::getinstance();

因為只有getinstance這個靜態函數,才能保證只調用一次mysql類的構造函數。

單例模式是很常用的設計模式,這里不再贅述。

外觀模式(facade)

因為命名空間的問題,外觀模式可以保證一個類的諸多方法看似是“一個類提供的”,這里我們先設計一個簡單的服務提供者類

?
1
2
3
4
5
class serviceprovider{
    public function write($arg){
        echo $arg;
    }
}

這個類只有一個write方法,就是把參數打印出來

然后定義一個facade類

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class facade{
    public static function getinstance($classname,$args){
        return new $classname($args);
    }
    
    public static function getfacadeaccessor(){
        //
    }
    
    public static function __callstatic($method,$args){
        $instance=static::getinstance(static::getfacadeaccessor(),$args);
        return call_user_func_array(array($instance,$method),$args);
    }
}

要理解這個類,我們只要關注最后一個函數,就是__callstatic魔術方法。這個方法就是facade類型對象或者其子類在調用他自身沒有定義過的函數時,就會調用__callstatic方法,而這個方法最后調用了call_user_func_array函數,就是把任務交給提供這項服務的類去完成,同時完成參數的傳遞。

我們再寫一個facade子類

?
1
2
3
4
5
class myfacade extends facade{
    public static function getfacadeaccessor(){
        return serviceprovider::class;
    }
}

這里注意,子類實現了父類沒有具體實現的getfacadeaccessor方法,這個方法就是要告訴父類的__callstatic方法:“我作為facade,代表的是什么哪個類,任務就由他來實現吧”,從語法上看,只是返回了一個表示類名的字符串。所以父類起初并不知道它的子類都代表著什么“服務提供者類”,只有當子類的靜態函數被調用后,因為子類沒有該靜態函數,所以父類的__callstatic方法被啟動了。

抽象工廠(factory)

我對抽象工廠有一個粗俗的理解:“對象與字符串的對應”,也就是用一個字符串就可以創造一個類的對象。這種做法主要用在兩種情況下是很方便的:

1.類名不穩定,會在項目中頻繁修改

類名修改,很多時候并不是設計者的“命名潔癖”或者“命名強迫癥”導致的修改,而是在項目的不斷迭代,發覺這個類設計的不合理。如果這個類用的不頻繁,那么改個類名只要手工做一些小的修改即可,但是如果這個類通篇存在于代碼之中(假如是數據庫類),那修改工作量就大了,當然,我們也可以對代碼文件使用“字符串替換”,但是假如一個php寫成的項目,php文件有幾十上百個,這也是不合理的事。

2.類的設計者并不是類的使用者

類的設計者和類的使用者不是同一個開發人員,那么記憶一個字符串或許比記憶一個類名要生動的多。我們都學過計算機網絡原理,都知道記憶一個域名要比記憶一個ip地址要生動的多,這就是dns解決的問題。

因為抽象工廠很多教材都有涉及,不再贅述,本文將介紹一下目前非常流行的服務容器。

我們希望整個工程項目中,db類,session類,filesystem類“拿來即用”,不用每次繁瑣的初始化,比如寫$db=new db(arg1,arg2);這類語句,也希望db等類型的對象像一個“全局”變量一般,在整個程序運行期間,隨時可以調用。

服務容器可以讓調用db等類型的程序員不用知道這個類太多的細節,甚至可以用一個字符串的別名來創建這樣一個對象。

我們定義一個服務容器類

?
1
2
3
4
5
6
7
8
9
class container{
    public $bindings;
    public function bind($abstract,$concrete){
        $this->bindings[$abstract]=$concrete;
    }
    public function make($abstract,$parameters=[]){
        return call_user_func_array($this->bindings[$abstract],$parameters);
    }
}

可以把服務容器簡單的看成一個全局變量,bind方法就是用關聯數組把字符串和構造函數做綁定。

至此,有了服務容器,我們的model類就要做修改了

?
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
class model implements imodel{
    public static $table;
    public static $container;
    
    public static $db;
    public function __construct(){
        self::$container=new container();
        self::$container->bind('db',function(){
            return mysql::getinstance();
        });
        
        self::$db=self::$container->make('db',[]);
    }
    
    public static function get($id){
        return self::where('id',$id);
    }
    
    public static function where($condition,$value){
        $sql=sprintf("select * from %s where %s='%s'",self::$table,$condition,$value);
        return self::$db->query($sql);
    }
 
    public static function all(){
        $sql=sprintf("select * from %s",self::$table);
        return self::$db->query($sql);
    }
}

觀察上面代碼,我們同時用了單例模式和服務容器。

總結:如果要做一個php框架,應該要做好代碼的復用。設計模式一直是很多爭論的焦點,“究竟該不該使用設計模式?”,本文開始,我也努力回避“過于糾結這個問題”,我認為,設計模式有其存在的價值,至少在具體項目中,確實在很多版本迭代中節省了工作量,提高工作效率,但是如果在一個小項目中為了“秀一下我會設計模式”而使用設計模式,就不合理了。

原文鏈接:http://www.cnblogs.com/sweng/p/6666008.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 美女黄网站免费观看 | 久久国产精品网 | 精品国内视频 | 亚欧美一区二区 | 一级毛片电影院 | 大奶一级片 | 日韩av一区三区 | 2021狠狠操 | 日韩 综合 | 久久久久亚洲国产精品 | 精品国产一区二区三区四区阿崩 | 亚洲国产精品久久久久制服红楼梦 | 久久精品视频69 | 国产精品一区二区三区在线 | 免费观看的毛片手机视频 | 精品亚洲夜色av98在线观看 | 欧美精品一区自拍a毛片在线视频 | 久久久久久中文字幕 | 欧美日韩国产成人在线 | 加勒比婷婷色综合久久 | 91久久九色| 热99在线视频 | 欧美一级视频在线 | 久久亚洲精品国产一区 | 欧美a在线观看 | 欧美a视频在线观看 | 欧美一级特黄aaaaaaa什 | 九九热在线视频观看 | 青青草最新网址 | 午夜影院在线免费观看 | wwwxxx免费视频| www.99久| 国产大片中文字幕在线观看 | 免费看成年人网站 | 国产精品视频yy9299一区 | 日韩a毛片免费观看 | 欧美黄色性生活视频 | 成人激情久久 | 国产99久久久久久免费看农村 | 免费国产一级特黄久久 | 羞羞视频免费网站男男 |