laravel用到的設(shè)計模式:工廠模式、單例模式、注冊樹模式、適配器模式、策略模式、數(shù)據(jù)對象映射模式、觀察者模式、原型模式、裝飾器模式、迭代器模式、代理模式等。
本教程操作環(huán)境:windows7系統(tǒng)、Laravel6版、Dell G3電腦。
本文給大家介紹了Laravel 中一些常用的設(shè)計模式,你一直都在用,可能你都不知道。。。
1:工廠模式
例如:Auth::user()
此處Auth這個類就是工廠中的方法,Auth是注冊樹中的別名。
好處:
類似于函數(shù)的封裝,使對象有一個統(tǒng)一的生成(實例化)入口。當(dāng)我們對象所對應(yīng)的類的類名發(fā)生變化的時候,我們只需要改一下工廠類類里面的實例化方法即可。
2:單例模式
好處:
對象不可外部實例化并且只能實例化一次,節(jié)省資源。
實現(xiàn)方式:
private static $ins = null; //設(shè)置私有的屬性 private function __construct() {} //使外部無法new這個類 public static function getIns() { //暴露給外部的調(diào)用方法 if(self::$ins instanceof self) { return self::$ins; } else { self::$ins = new self(); return self::$ins; } }
聲明一個類的私有或者保護的靜態(tài)變量,構(gòu)造方法聲明為私有(不允許外部進行new操作),如果不存在則實例化它,然后返回,如果存在則直接返回。
3:注冊樹模式
使用:
config/app里的aliases數(shù)組便是一個注冊樹
好處:
注冊樹模式就是使用數(shù)組結(jié)構(gòu)來存取對象,工廠方法只需要調(diào)用一次(可以放到系統(tǒng)環(huán)境初始化這樣的地方),以后需要調(diào)用該對象的時候直接從注冊樹上面取出來即可,不需要再調(diào)用工廠方法和單例模式。
實現(xiàn)方法:
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::$onjects[$alias]); } }
$alias表示別名,自己設(shè)定
在工廠模式中添加
Register::set(‘db1’,$db);
其他任何地方調(diào)用只需要調(diào)用注冊器讀取即可
Register::$objects[‘db1’];
4:適配器模式
將不同工具的不同函數(shù)接口封裝成統(tǒng)一的API,方便調(diào)用。如:mysql,mysqli,PDO。
實現(xiàn):在接口類里面申明統(tǒng)一的方法體,再讓不同的類去實現(xiàn)這個接口,和重寫其抽象方法。
interface?Database?{?????????????????????????????????????????????????? ????????function?connect($host,$user,$password,$dbname); ????????function?query($sql); ????????function?close(); ????}
然后再去用不同的工具函數(shù)去實現(xiàn)相同的接口。
5:策略模式
好處:
將一組特定的行為和算法封裝成類,以適應(yīng)某些特定的上下文環(huán)境,將邏輯判斷和具體實現(xiàn)分離,實現(xiàn)了硬編碼到解耦,并可實現(xiàn)IOC、依賴倒置、反轉(zhuǎn)控制。
實現(xiàn):
1.定義一個策略接口文件(UserStrategy.php),定義策略接口,聲明策略
2.定義具體類(FemaleUserStrategy.php,MaleUserStrategy.php),實現(xiàn)策略接口,重寫策略方法
class Page { protected $strategy; function index() { if($request->get('female')) { $strategy=new FemaleUserStrategy(); } else { $strategy=new MaleUserStrategy(); } $this->strategy->method(); } public function __construct(UserStrategy $strategy) { $this->strategy=$strategy; } }
6:數(shù)據(jù)對象映射模式
好處:將對象和數(shù)據(jù)存儲映射起來,對一個對象的操作會映射為對數(shù)據(jù)存儲的操作,這也是ORM的實現(xiàn)機制。
class Model { public $id; public $name; public $email; …… function __construct($id) { //構(gòu)造函數(shù),調(diào)用class時自動執(zhí)行,用來初始化。 //查詢邏輯 } function __destruct() { //析構(gòu)函數(shù),當(dāng)class調(diào)用完成后自動執(zhí)行,用它來銷毀實例,釋放資源。 //增刪改邏輯 } }
7:觀察者模式
使用:
觸發(fā)類Event
<?php namespace AppEvents; abstract class Event { //邏輯代碼 }
監(jiān)聽類EventListener
<?php namespace AppListeners; use AppEventsSomeEvent; use IlluminateQueueInteractsWithQueue; use IlluminateContractsQueueShouldQueue; class EventListener { /** * Create the event listener. * * @return void */ public function __construct() { // } /** * Handle the event. * * @param SomeEvent $event * @return void */ public function handle(SomeEvent $event) { // } }
好處:
當(dāng)一個對象狀態(tài)發(fā)生改變時,依賴它的對象全部會收到通知并自動更新,實現(xiàn)低耦合,非侵入式的通知與更新機制。
8:原型模式
與工廠模式類似,用于創(chuàng)建對象,不同在于:原型模式是先創(chuàng)建好一個原型對象,再通過clone原型對象來創(chuàng)建新的對象,原型模式適用于大對象的創(chuàng)建,僅需要內(nèi)存拷貝即可。
$Object?=?new?Object(); $object_1?=?clone?$Object; $object_2?=?clone?$Object;
9:裝飾器模式
若要修改或添加一個類的功能,傳統(tǒng)的方式是寫一個子類繼承它,并重新實現(xiàn)類的方法。裝飾器模式僅需在運行時添加一個裝飾器對象即可動態(tài)的添加或修改類的功能。
傳統(tǒng)方法:
class?Method2?extends?Method?{ ????????function?doSomething()?{ ????????????????echo?"<div>" ????????????????parent::doSomething(); ????????????????echo?"</div>"; ????????} } interfa?Decorator?{?????????????????????????????????????????????//定義裝飾器接口 ????????function?beforeAction(); ????????function?afterAction(); ????????//more?decoratorMethod…… } class?SomeClass?{ ????????protected?$decorators?=?[]; ????????function?addDecorator(Decorator?$decorator)?{ ????????????????$this->decorators[]?=?$decorator; ????????} ????????function?beforeMethod()?{ ????????????????foreach?($this->decorators?as?$row)?{ ????????????????????????$row->beforeAction(); ????????????????} ????????} ????????function?afterMethod()?{ ????????????????$decorators?=?array_reverse($this->decorators);?????//做一個反轉(zhuǎn) ????????????????foreach?($this->decorators?as?$row)?{ ????????????????????????$row->afterAction(); ????????????????} ????????} ????????function?action()?{ ????????????????$this->beforeMethod(); ????????????????//method; ????????????????$this->afterMethod(); ????????} } class?OneDecorator?implements?Decorator?{ ????????protected?$datas; ????????function?__construct($datas?=?'request')?{ ?????????????????$this->datas?=?$datas; ????????} ????????function?beforeAction()?{ ??????????????????echo?"<div>datas};'>"; ????????} ????????function?afterAction()?{ ??????????????????echo?"</div>"; ????????} } $Object?=?new?SomeClass(); $Object->addDecorator(new?OneDecorator('blue')); //Add?other?decorator... $Object->action();
10:迭代器模式
在不需要了解內(nèi)部實現(xiàn)的前提下,遍歷一個聚合對象的內(nèi)部元素,相對于傳統(tǒng)編程方式它可以遍歷元素所需的操作。
例如:
Object::all() Iterator?extends?Traversable?{???????????????????????//PHP內(nèi)置迭代器接口 /*?方法?*/ ????????abstract?public?mixed?current?(void) ????????abstract?public?scalar?key?(void) ????????abstract?public?void?next?(void) ????????abstract?public?void?rewind?(void) ????????abstract?public?boolean?valid?(void) } class?ObjectAll?implements?Iterator?{ ????????protected?$ids;??????????????????????//所有對象的id ????????protected?$index;??????????????????//迭代器的當(dāng)前位置 ????????protected?$data?=?array();?????//保存從數(shù)據(jù)庫取到的所有對象 ????????function?__construct()?{ ????????//取出所有的id,$ids } ????????function?current()?{ ????????????????//獲取當(dāng)前的元素的數(shù)據(jù),第三個調(diào)用 ????????????????$id?=?$this->ids[$this->index]['id']; ????????????????return?Object::find($id); ????????} ????????function?next()?{ ????????????????//獲取下一個元素,第四個調(diào)用 ????????????????$this->index?++; ?????????} ?????????function?valid()?{ ?????????????????//驗證當(dāng)前元素是否還有下一個元素(查詢當(dāng)前是否有數(shù)據(jù)),第二個調(diào)用 ?????????????????return?$this->index?$ids); ?????????} ?????????function?rewind()?{ ?????????????????//當(dāng)?shù)鲌?zhí)行到末尾時,重置迭代器到整個集合的開頭,最先調(diào)用 ?????????????????$this->index?=?0; ?????????} ?????????function?key()?{ ??????????????????//獲取當(dāng)前的索引,最后調(diào)用 ??????????????????return?$this->index; ?????????} } $objects?=?new?ObjectAll(); foreach?($objects?as?$row)?{ ????????dump($row->field); ????????//增刪改查操作 }
11:代理模式
在客戶端與實體之間建立一個代理對象,客戶端對實體進行操作全部委派給代理對象,隱藏實體的具體實現(xiàn)細節(jié)(slave讀庫與master寫庫分離)。代理對象還可以與業(yè)務(wù)代碼分離,部署到另外的服務(wù)器,業(yè)務(wù)代碼中通過PRC來委派任務(wù)。
interface?DBproxy?{ ????????function?getInfo($id); ????????function?setInfo($id,?$value); } class?Proxy?implements?DBproxy?{ ????????function?get()?{ ????????????????//DB::('slave'); ????????????????query ????????} ????????function?set()?{ ????????????????//DB::('master'); ????????????????query ????????} } $proxy?=?new?Proxy(); $proxy->get($id); $proxy->set($id,?$value);
相關(guān)推薦:最新的五個Laravel視頻教程