一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語(yǔ)言|JavaScript|易語(yǔ)言|vb.net|

服務(wù)器之家 - 編程語(yǔ)言 - PHP教程 - 自制PHP框架之設(shè)計(jì)模式

自制PHP框架之設(shè)計(jì)模式

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

本文是自制PHP框架的第三篇,我們主要來(lái)講解下PHP的設(shè)計(jì)模式的使用,本文我們一起來(lái)學(xué)習(xí)PHP中最常用的三種設(shè)計(jì)模式:?jiǎn)卫O(shè)計(jì)模式、工廠設(shè)計(jì)模式和觀察者設(shè)計(jì)模式。

為什么要使用設(shè)計(jì)模式

設(shè)計(jì)模式,我的理解是為了達(dá)到“可復(fù)用”這個(gè)目標(biāo),而設(shè)計(jì)的一套相互協(xié)作的類。

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

這里先介紹我們框架要涉及的三種設(shè)計(jì)模式。

單例模式(singleton)

單例模式可以保證一個(gè)類只有一個(gè)對(duì)象實(shí)例, 常用在數(shù)據(jù)庫(kù)存取類,從而節(jié)省硬件資源的消耗。

這里,我們改寫上一章節(jié)的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);
    }
}

這里要注意的是,如果實(shí)例化一個(gè)mysql類,我們不再寫

?
1
$db=new mysql();

而是這樣:

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

因?yàn)橹挥術(shù)etinstance這個(gè)靜態(tài)函數(shù),才能保證只調(diào)用一次mysql類的構(gòu)造函數(shù)。

單例模式是很常用的設(shè)計(jì)模式,這里不再贅述。

外觀模式(facade)

因?yàn)槊臻g的問(wèn)題,外觀模式可以保證一個(gè)類的諸多方法看似是“一個(gè)類提供的”,這里我們先設(shè)計(jì)一個(gè)簡(jiǎn)單的服務(wù)提供者類

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

這個(gè)類只有一個(gè)write方法,就是把參數(shù)打印出來(lái)

然后定義一個(gè)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);
    }
}

要理解這個(gè)類,我們只要關(guān)注最后一個(gè)函數(shù),就是__callstatic魔術(shù)方法。這個(gè)方法就是facade類型對(duì)象或者其子類在調(diào)用他自身沒(méi)有定義過(guò)的函數(shù)時(shí),就會(huì)調(diào)用__callstatic方法,而這個(gè)方法最后調(diào)用了call_user_func_array函數(shù),就是把任務(wù)交給提供這項(xiàng)服務(wù)的類去完成,同時(shí)完成參數(shù)的傳遞。

我們?cè)賹懸粋€(gè)facade子類

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

這里注意,子類實(shí)現(xiàn)了父類沒(méi)有具體實(shí)現(xiàn)的getfacadeaccessor方法,這個(gè)方法就是要告訴父類的__callstatic方法:“我作為facade,代表的是什么哪個(gè)類,任務(wù)就由他來(lái)實(shí)現(xiàn)吧”,從語(yǔ)法上看,只是返回了一個(gè)表示類名的字符串。所以父類起初并不知道它的子類都代表著什么“服務(wù)提供者類”,只有當(dāng)子類的靜態(tài)函數(shù)被調(diào)用后,因?yàn)樽宇悰](méi)有該靜態(tài)函數(shù),所以父類的__callstatic方法被啟動(dòng)了。

抽象工廠(factory)

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

1.類名不穩(wěn)定,會(huì)在項(xiàng)目中頻繁修改

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

2.類的設(shè)計(jì)者并不是類的使用者

類的設(shè)計(jì)者和類的使用者不是同一個(gè)開發(fā)人員,那么記憶一個(gè)字符串或許比記憶一個(gè)類名要生動(dòng)的多。我們都學(xué)過(guò)計(jì)算機(jī)網(wǎng)絡(luò)原理,都知道記憶一個(gè)域名要比記憶一個(gè)ip地址要生動(dòng)的多,這就是dns解決的問(wèn)題。

因?yàn)槌橄蠊S很多教材都有涉及,不再贅述,本文將介紹一下目前非常流行的服務(wù)容器。

我們希望整個(gè)工程項(xiàng)目中,db類,session類,filesystem類“拿來(lái)即用”,不用每次繁瑣的初始化,比如寫$db=new db(arg1,arg2);這類語(yǔ)句,也希望db等類型的對(duì)象像一個(gè)“全局”變量一般,在整個(gè)程序運(yùn)行期間,隨時(shí)可以調(diào)用。

服務(wù)容器可以讓調(diào)用db等類型的程序員不用知道這個(gè)類太多的細(xì)節(jié),甚至可以用一個(gè)字符串的別名來(lái)創(chuàng)建這樣一個(gè)對(duì)象。

我們定義一個(gè)服務(wù)容器類

?
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);
    }
}

可以把服務(wù)容器簡(jiǎn)單的看成一個(gè)全局變量,bind方法就是用關(guān)聯(lián)數(shù)組把字符串和構(gòu)造函數(shù)做綁定。

至此,有了服務(wù)容器,我們的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);
    }
}

觀察上面代碼,我們同時(shí)用了單例模式和服務(wù)容器。

總結(jié):如果要做一個(gè)php框架,應(yīng)該要做好代碼的復(fù)用。設(shè)計(jì)模式一直是很多爭(zhēng)論的焦點(diǎn),“究竟該不該使用設(shè)計(jì)模式?”,本文開始,我也努力回避“過(guò)于糾結(jié)這個(gè)問(wèn)題”,我認(rèn)為,設(shè)計(jì)模式有其存在的價(jià)值,至少在具體項(xiàng)目中,確實(shí)在很多版本迭代中節(jié)省了工作量,提高工作效率,但是如果在一個(gè)小項(xiàng)目中為了“秀一下我會(huì)設(shè)計(jì)模式”而使用設(shè)計(jì)模式,就不合理了。

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

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 欧美男同video| 大伊香蕉精品二区视频在线 | 日本国产成人精品视频 | 日本草草视频在线观看 | 亚洲精品一区二区久久这里 | 农夫69小说小雨与农村老太 | 亚洲国产日韩欧美一区二区三区 | 日日插插| 国产在视频线精品视频 | 2022国产麻豆剧果冻传媒入口 | 久久久久琪琪精品色 | 成人aaaa| 精品视频网站 | 贰佰麻豆剧果冻传媒一二三区 | 日韩毛片在线视频 | 国内精品露脸在线视频播放 | 久久免费看少妇高潮A片特爽 | 精品国产区一区二区三区在线观看 | 亚洲 欧美 中文 日韩欧美 | 成年人视频免费在线播放 | 爱情岛论坛亚洲自拍 | 国内精品久久久久久野外 | 国产剧情一区 | 国产精品香蕉在线观看不卡 | 成人精品免费网站 | 咪咪爱991| 糖心vlog视频永久破解版 | 摸逼网| 亚洲欧洲日产国码天堂 | www日本视频 | 国产精品视频人人做人人爱 | 视频免费观看在线播放高清 | 国产午夜精品久久理论片小说 | 日韩精品免费一区二区三区 | 欧美草比视频 | 狠狠涩 | 91桃色视频 | 赤坂丽女医bd无删减在线观看 | 精品一区二区三区五区六区七区 | 四虎影院免费在线播放 | 亚洲精品中文字幕久久久久久 |