摘要:框架源碼一常用的四種數(shù)據(jù)結(jié)構(gòu)簡(jiǎn)介是的一個(gè)標(biāo)準(zhǔn)庫(kù)。五其他常見的種設(shè)計(jì)模式適配器模式將一個(gè)類的接口轉(zhuǎn)換成客戶希望的另一個(gè)接口適配器模式使得原本的由于接口不兼容而不能一起工作的那些類可以一起工作。場(chǎng)景一個(gè)事件發(fā)生后,要執(zhí)行一連串更新操作。
phpms框架源碼https://github.com/wuxiumu/ms一、PHP常用的四種數(shù)據(jù)結(jié)構(gòu)
簡(jiǎn)介:spl是php的一個(gè)標(biāo)準(zhǔn)庫(kù)。
官方文檔:http://php.net/manual/zh/book...
push("data1");//入棧(先進(jìn)后出) $stack->push("data2");//入棧 $stack->push("data3");//入棧 echo $stack->pop().PHP_EOL;//出棧 echo $stack->pop().PHP_EOL;//出棧 echo $stack->pop().PHP_EOL;//出棧 } /** *隊(duì)列(先進(jìn)先出) */ function duilie(){ $queue = new SplQueue(); $queue->enqueue("data4");//入隊(duì)列 $queue->enqueue("data5");//入隊(duì)列 $queue->enqueue("data6");//入隊(duì)列 echo $queue->dequeue().PHP_EOL;//出隊(duì)列 echo $queue->dequeue().PHP_EOL;//出隊(duì)列 echo $queue->dequeue().PHP_EOL;//出隊(duì)列 } /** * 堆 */ function dui(){ $heap = new SplMinHeap(); $heap->insert("data8");//入堆 $heap->insert("data9");//入堆 $heap->insert("data10");//入堆 echo $heap->extract().PHP_EOL;//從堆中提取數(shù)據(jù) echo $heap->extract().PHP_EOL;//從堆中提取數(shù)據(jù) echo $heap->extract().PHP_EOL;//從堆中提取數(shù)據(jù) } /** * 固定數(shù)組(不論使不使用,都會(huì)分配相應(yīng)的內(nèi)存空間) */ $array = new SplFixedArray(15); $array["0"] = 54; $array["6"] = 69; $array["10"] = 32; var_dump($array);二、PHP鏈?zhǔn)讲僮鞯膶?shí)現(xiàn)(原理) 1、入口文件
index.php
header("content-type:text/html;charset=utf-8"); define("PHPMSFRAME",__DIR__); define("CORE",PHPMSFRAME."/core"); define("APP",PHPMSFRAME."/app"); define("MODULE","app"); define("DEBUG",true); include "vendor/autoload.php"; if(DEBUG){ $whoops = new WhoopsRun; $whoops->pushHandler(new WhoopsHandlerPrettyPageHandler); $whoops->register(); ini_set("display_error", "On"); }else{ ini_set("display_error", "Off"); } include CORE."/common/function.php"; include CORE."/phpmsframe.php"; spl_autoload_register("corephpmsframe::load"); corephpmsframe::run();2、自動(dòng)加載類
corephpmsframe.php
ctrl; $action = $route->action; $ctrlfile = APP."/ctrl/".$ctrlClass."Ctrl.php"; $ctrlClass = "".MODULE."ctrl".$ctrlClass."Ctrl"; if(is_file($ctrlfile)){ include $ctrlfile; $ctrl = new $ctrlClass(); $ctrl->$action(); }else{ $msg = "控制器 $ctrlClass 不存在 "; self::reportingDog($msg); } } static public function load($class) { if(isset($classMap[$class])){ return true; }else{ $class = str_replace("", "/", $class); $file = PHPMSFRAME."/".$class.".php"; if(is_file($file)){ include $file; self::$classMap[$class] = $class; }else{ return false; } } } public function assign($name,$value){ $this->assign[$name]=$value; } public function display($file){ $file_path = APP."/views/".$file; if(is_file($file_path)){ /***********twig模板***********/ $loader = new Twig_Loader_Filesystem(APP."/views"); $twig = new Twig_Environment($loader, array( "cache" => PHPMSFRAME."/cache", "debug"=>DEBUG, )); $template = $twig->load($file); $template->display($this->assign?$this->assign:""); /***********twig模板e(cuò)nd***********/ /***********原生模板***********/ //extract($this->assign); //include $file_path; /***********原生模板e(cuò)nd***********/ } } static private function reportingDog($msg){ echo $msg." "; include "smile/havefun.php"; $num = str_pad(rand(00,32),2,"0",STR_PAD_LEFT); $num = "str_".$num; $Parsedown = new Parsedown(); echo $Parsedown->text($$num); $num = "str_".rand(50,84); echo $Parsedown->text($$num); exit; } }3、數(shù)據(jù)庫(kù)類
注:只是原理,并沒有對(duì)方法進(jìn)行具體的封裝,具體的封裝還是看個(gè)人喜好去定鏈?zhǔn)讲樵兊娘L(fēng)格。
corelibmodel.php
corelibdrivedatabasemedooModel.php
三、PHP魔術(shù)方法的使用在php設(shè)計(jì)模式中,會(huì)涉及到很多魔術(shù)方法的使用,這里也對(duì)經(jīng)常會(huì)用到的魔術(shù)方法進(jìn)行簡(jiǎn)單總結(jié)。
1、框架入口文件corephpmsframe.php
/** * 魔術(shù)方法的使用 */ /* 這是一個(gè)魔術(shù)方法,當(dāng)一個(gè)對(duì)象或者類獲取其不存在的屬性的值時(shí), * 如:$obj = new BaseController ; * $a = $obj -> a ; * 該方法會(huì)被自動(dòng)調(diào)用,這樣做很友好,可以避免系統(tǒng)報(bào)錯(cuò) */ public function __get($property_name){ $msg = "屬性 $property_name 不存在 "; self::reportingDog($msg); } /* 這是一個(gè)魔術(shù)方法,當(dāng)一個(gè)對(duì)象或者類給其不存在的屬性賦值時(shí), * 如:$obj = new BaseController ; * $obj -> a = 12 ; * 該方法(__set(屬性名,屬性值))會(huì)被自動(dòng)調(diào)用,這樣做很友好,可以避免系統(tǒng)報(bào)錯(cuò) */ public function __set($property_name,$value){ $msg = "屬性 $property_name 不存在 "; self::reportingDog($msg); } /* 這是一個(gè)魔術(shù)方法,當(dāng)一個(gè)對(duì)象或者類的不存在屬性進(jìn)行isset()時(shí), * 注意:isset 用于檢查一個(gè)量是否被賦值 如果為NULL會(huì)返回false * 如:$obj = new BaseController ; * isset($obj -> a) ; * 該方法會(huì)被自動(dòng)調(diào)用,這樣做很友好,可以避免系統(tǒng)報(bào)錯(cuò) */ public function __isset($property_name){ $msg = "屬性 $property_name 不存在 "; self::reportingDog($msg); } /* 這是一個(gè)魔術(shù)方法,當(dāng)一個(gè)對(duì)象或者類的不存在屬性進(jìn)行unset()時(shí), * 注意:unset 用于釋放一個(gè)變量所分配的內(nèi)存空間 * 如:$obj = new BaseController ; * unset($obj -> a) ; * 該方法會(huì)被自動(dòng)調(diào)用,這樣做很友好,可以避免系統(tǒng)報(bào)錯(cuò) */ public function __unset($property_name){ $msg = "屬性 $property_name 不存在 "; self::reportingDog($msg); } /* 當(dāng)對(duì)這個(gè)類的對(duì)象的不存在的實(shí)例方法進(jìn)行“調(diào)用”時(shí),會(huì)自動(dòng)調(diào)用該方法, * 這個(gè)方法有2個(gè)參數(shù)(必須帶有的): * $methodName 表示要調(diào)用的不存在的方法名; * $argument 是一個(gè)數(shù)組,表示要調(diào)用該不存在的方法時(shí),所使用的實(shí)參數(shù)據(jù), */ public function __call($methodName,$argument){ $msg = "實(shí)例方法 $methodName 不存在 "; self::reportingDog($msg); }四、三種基礎(chǔ)設(shè)計(jì)模式 1、工廠模式通過傳入?yún)?shù)的不同,來實(shí)例化不同的類。
$cache =CoreextendCacheFactory::getCacheObj("redis",array( "host" => "127.0.0.1", "pass" => "myRedis&&&" )); var_dump($cache);coreextendCacheFactory.php
2、單例模式保證一個(gè)類只實(shí)例化一個(gè)類對(duì)象,進(jìn)而減少系統(tǒng)開銷和資源的浪費(fèi)
//單例模式創(chuàng)建對(duì)象 $obj = ExtendSingleObject::getInstance(); $obj2 = ExtendSingleObject::getInstance(); var_dump($obj,$obj2);//從結(jié)果可以看出,兩個(gè)實(shí)例化的對(duì)象其實(shí)是一個(gè)對(duì)象coreextendSingleObject.php
3、注冊(cè)樹模式將我們用到的對(duì)象注冊(cè)到注冊(cè)樹上,然后在之后要用到這個(gè)對(duì)象的時(shí)候,直接從注冊(cè)樹上取下來就好。(就和我們用全局變量一樣方便)
coreextendRegisterTree,php
關(guān)于注冊(cè)樹模式,這里推薦一篇文章 ,可以方便理解。 https://segmentfault.com/a/11...
五、其他常見的8種PHP設(shè)計(jì)模式 1、適配器模式將一個(gè)類的接口轉(zhuǎn)換成客戶希望的另一個(gè)接口,適配器模式使得原本的由于接口不兼容而不能一起工作的那些類可以一起工作。
應(yīng)用場(chǎng)景:老代碼接口不適應(yīng)新的接口需求,或者代碼很多很亂不便于繼續(xù)修改,或者使用第三方類庫(kù)。常見的有兩種適配器,分別是類適配器和對(duì)象適配器,這里拿更看好的對(duì)象適配器舉例:
"; } } /** * 類適配器角色(新定義接口的具體實(shí)現(xiàn)) * Class Adapter * @package Extend */ class Adapter implements Target { private $adaptee; function __construct() { //適配器初始化直接new 原功能類,以方便之后委派 $adaptee = new Adaptee(); $this->adaptee = $adaptee; } //委派調(diào)用Adaptee的sampleMethod1方法 public function simpleMethod1() { echo $this->adaptee->simpleMethod1(); } public function simpleMethod2() { echo "Adapter simpleMethod2"."
"; } } /** * 客戶端調(diào)用 */ $adapter = new Adapter(); $adapter->simpleMethod1(); $adapter->simpleMethod2();這篇文章介紹了類適配器的使用,感興趣的可以了解一下 https://segmentfault.com/a/11...
2、策略模式將一組特定的行為和算法封裝成類,以適應(yīng)某些特定的上下文環(huán)境,這種模式就是策略模式,策略模式可以實(shí)現(xiàn)依賴倒置以及控制反轉(zhuǎn)。
實(shí)例舉例:假如一個(gè)電商網(wǎng)站系統(tǒng),針對(duì)男性女性用戶要各自跳轉(zhuǎn)到不同的商品類目,并且所有的廣告位展示展示不同的廣告。
userType->showAd(); echo "Category:"; $this->userType->showCategory(); } /** * 策略模式 * 根據(jù)傳遞的用戶性別展示不同類別數(shù)據(jù) * @param ExtendUserType $userType */ function setUserType(ExtendUserType $userType) { $this->userType = $userType; } } $obj = new Home(); if ($_GET["userType"] == "female"){ $userType = new ExtendFemaleUserType(); } else { $userType = new ExtendMaleUserType(); } $obj->setUserType($userType); $obj->index();Extend/userType.php(定義的接口)
MaleUserType.php、FemaleUserType.php(具體實(shí)現(xiàn)的類 )
3、數(shù)據(jù)對(duì)象映射模式將對(duì)象和數(shù)據(jù)存儲(chǔ)映射起來,對(duì)一個(gè)對(duì)象的操作會(huì)映射為對(duì)數(shù)據(jù)存儲(chǔ)的操作。
下面在代碼中實(shí)現(xiàn)數(shù)據(jù)對(duì)象映射模式,我們將實(shí)現(xiàn)一個(gè)ORM類,將復(fù)雜的sql語(yǔ)句映射成對(duì)象屬性的操作。并結(jié)合使用數(shù)據(jù)對(duì)象映射模式、工廠模式、注冊(cè)模式。
?
(1)數(shù)據(jù)庫(kù)映射模式簡(jiǎn)單實(shí)例實(shí)現(xiàn)
name = "小卜丟飯團(tuán)子"; $user->salary = "20000"; $user->city = "浙江省";Extend/User.php
id = $id; $this->pdo = new PDO("mysql:host=127.0.0.1;dbname=test","root","123456"); } function __destruct() { $this->pdo->query("update user set name = "{$this->name}",salary = "{$this->salary}",city = "{$this->city}" where id="{$this->id}""); } }這樣,執(zhí)行index.php文件,數(shù)據(jù)庫(kù)就會(huì)發(fā)生相應(yīng)的操作,也就實(shí)現(xiàn)了基本的數(shù)據(jù)對(duì)象映射。
(2)數(shù)據(jù)庫(kù)映射模式復(fù)雜案例實(shí)現(xiàn)
name = "小卜丟飯團(tuán)子"; $user->salary = "20000"; $user->city = "浙江省"; } function test() { $user = ExtendFactory::getUserObj(25); $user->city = "廣東省"; } } $ex = new EX(); $ex->index();Extend/Factory.php
Extend/Register.php
Extend/User.php
id = $id; $this->pdo = new PDO("mysql:host=127.0.0.1;dbname=test","root","123456"); } function __destruct() { $this->pdo->query("update user set name = "{$this->name}",salary = "{$this->salary}",city = "{$this->city}" where id="{$this->id}""); } }這樣,就實(shí)現(xiàn)了稍復(fù)雜的數(shù)據(jù)對(duì)象映射模式和工廠模式、注冊(cè)樹模式相結(jié)合的案例。
?
4、觀察者模式當(dāng)一個(gè)對(duì)象狀態(tài)發(fā)生改變時(shí),依賴它的對(duì)象會(huì)全部收到通知,并自動(dòng)更新。
場(chǎng)景:一個(gè)事件發(fā)生后,要執(zhí)行一連串更新操作。傳統(tǒng)的編程方式就是在事件的代碼之后直接加入處理邏輯,當(dāng)更新的邏輯增多之后,代碼會(huì)變的難以維護(hù)。這種方式是耦合的,侵入式的,增加新的邏輯需要修改事件主體的代碼。觀察者模式實(shí)現(xiàn)了低耦合,非侵入式的通知與更新機(jī)制。
?
4.1、傳統(tǒng)模式舉例:"; //傳統(tǒng)方式是在發(fā)生一個(gè)事件之后直接進(jìn)行一系列的相關(guān)處理,耦合度比較高,比如寫入日志,給用戶發(fā)郵件等等 echo "在用戶下單之后進(jìn)行的一系列操作4.2、觀察者模式典型實(shí)現(xiàn)方式:
"; } } $event = new Event(); $event->firmOrder();(1)定義2個(gè)接口:觀察者(通知)接口、被觀察者(主題)接口
(2)定義2個(gè)類,觀察者類實(shí)現(xiàn)觀察者接口、被觀察者類實(shí)現(xiàn)被觀察者接口
(3)被觀察者注冊(cè)自己需要通知的觀察者
(4)被觀察者類某個(gè)業(yè)務(wù)邏輯發(fā)生時(shí),通知觀察者對(duì)象,進(jìn)而每個(gè)觀察者執(zhí)行自己的業(yè)務(wù)邏輯。
代碼示例:
observers[] = $observer; } /** * 購(gòu)票主體方法 * BuyTicket constructor. * @param $ticket 購(gòu)票排號(hào) */ public function buyTicket($ticket) { //1、根據(jù)需求寫購(gòu)票邏輯 //.............. //2、購(gòu)票成功之后,循環(huán)通知觀察者,并調(diào)用其buyTicketOver實(shí)現(xiàn)不同業(yè)務(wù)邏輯 foreach ($this->observers as $observe) { $observe->buyTicketOver($this, $ticket); //$this 可用來獲取主題類句柄,在通知中使用 } } } /** * 購(gòu)票成功后,發(fā)送短信通知 * Class buyTicketMSN */ class buyTicketMSN implements TicketObserver { public function buyTicketOver($sender, $ticket) { echo (date ( "Y-m-d H:i:s" ) . " 短信日志記錄:購(gòu)票成功:$ticket5、原型模式
"); } } /** * 購(gòu)票成功后,記錄日志 * Class buyTicketLog */ class buyTicketLog implements TicketObserver { public function buyTicketOver($sender, $ticket) { echo (date ( "Y-m-d H:i:s" ) . " 文本日志記錄:購(gòu)票成功:$ticket
"); } } /** * 購(gòu)票成功后,贈(zèng)送優(yōu)惠券 * Class buyTicketCoupon */ class buyTicketCoupon implements TicketObserver { public function buyTicketOver($sender, $ticket) { echo (date ( "Y-m-d H:i:s" ) . " 贈(zèng)送優(yōu)惠券:購(gòu)票成功:$ticket 贈(zèng)送10元優(yōu)惠券1張。
"); } } //實(shí)例化購(gòu)票類 $buy = new BuyTicket(); //添加多個(gè)觀察者 $buy->addObserver(new buyTicketMSN()); $buy->addObserver(new buyTicketLog()); $buy->addObserver(new buyTicketCoupon()); //開始購(gòu)票 $buy->buyTicket ("7排8號(hào)");原型模式與工廠模式的作用類似,都是用來創(chuàng)建對(duì)象的。但是實(shí)現(xiàn)方式是不同的。原型模式是先創(chuàng)建好一個(gè)原型對(duì)象,然后通過clone原型對(duì)象來創(chuàng)建新的對(duì)象。這樣,就免去了類創(chuàng)建時(shí)重復(fù)的初始化操作。
原型模式適用于大對(duì)象的創(chuàng)建,創(chuàng)建一個(gè)大對(duì)象需要很大的開銷,如果每次new就會(huì)消耗很大,原型模式僅需內(nèi)存拷貝即可。
代碼實(shí)例:
_name = $name; } public function setName($name) { $this->_name = $name; } public function getName() { return $this->_name; } public function copy() { //深拷貝實(shí)現(xiàn) //$serialize_obj = serialize($this); // 序列化 //$clone_obj = unserialize($serialize_obj); // 反序列化 //return $clone_obj; // 淺拷貝實(shí)現(xiàn) return clone $this; } } /** * 測(cè)試深拷貝用的引用類 */ class Demo { public $array; } //測(cè)試 $demo = new Demo(); $demo->array = array(1, 2); $object1 = new ConcretePrototype($demo); $object2 = $object1->copy(); var_dump($object1->getName()); echo "
"; var_dump($object2->getName()); echo "
"; $demo->array = array(3, 4); var_dump($object1->getName()); echo "
"; var_dump($object2->getName()); echo "
";關(guān)于原型模式文章:https://www.imooc.com/article...
6、裝飾器模式可以動(dòng)態(tài)的添加或修改類的功能
一個(gè)類實(shí)現(xiàn)一個(gè)功能,如果要再修改或添加額外的功能,傳統(tǒng)的編程模式需要寫一個(gè)子類繼承它,并重新實(shí)現(xiàn)類的方法。
使用裝飾器模式,僅需在運(yùn)行時(shí)添加一個(gè)裝飾器對(duì)象即可實(shí)現(xiàn),可以實(shí)現(xiàn)最大的靈活性。
color = $color; } public function beforeEcho() { echo ""; } public function afterEcho() { echo "
在不需要了解內(nèi)部實(shí)現(xiàn)的前提下,遍歷一個(gè)聚合對(duì)象的內(nèi)部元素而又不暴露該對(duì)象的內(nèi)部表示,這就是PHP迭代器模式的定義。
相對(duì)于傳統(tǒng)編程模式,迭代器模式可以隱藏遍歷元素的所需的操作。
Extend/AllUser.php
pdo = new PDO("mysql:host=127.0.0.1;dbname=test","root","123456"); //獲取所有用戶的id $this->ids = $this->pdo->query("select id from user")->fetchAll(2); } /** * 實(shí)現(xiàn)接口方法,重置迭代器,回到集合開頭 */ public function rewind() { $this->index = 0; } /** * 實(shí)現(xiàn)接口方法,獲取當(dāng)前元素 * @return mixed|void */ public function current() { $id = $this->ids[$this->index]["id"]; //獲取當(dāng)前用戶的數(shù)據(jù) $user_data = $this->pdo->query("select * from user where id="{$id}"")->fetch(2); return $user_data; } /** * 實(shí)現(xiàn)接口方法,獲取當(dāng)前元素鍵值 * @return mixed|void */ public function key() { return $this->index; } /** * 實(shí)現(xiàn)接口方法,獲取下一個(gè)元素 */ public function next() { $this->index++; } /** * 實(shí)現(xiàn)接口方法,驗(yàn)證是否還有下一個(gè)元素 * @return bool|void */ public function valid() { return $this->index < count($this->ids); } }關(guān)于php迭代器文章?http://www.php.cn/php-weiziji...
?
8、代理模式在客戶端與實(shí)體之間建立一個(gè)代理對(duì)象(proxy),客戶端對(duì)實(shí)體進(jìn)行操作全部委派給代理對(duì)象,隱藏實(shí)體的具體實(shí)現(xiàn)細(xì)節(jié)。
典型的應(yīng)用就是mysql的主從結(jié)構(gòu),讀寫分離。在mysql中,對(duì)所有讀的操作請(qǐng)求從庫(kù),所有寫的操作請(qǐng)求主庫(kù)。
聲明一個(gè)代理類,前臺(tái)使用時(shí)只需創(chuàng)建一個(gè)代理類,調(diào)用對(duì)應(yīng)方法即可。代碼實(shí)例:
query("select * from user where id = 1 limit 1"); #增刪改操作使用主庫(kù) //$db_master = ExtendFactory::getDatabase("master"); //$db_master->query("update user name = "xiaobudiu" where id = 29 limit 1"); // 2、使用代理模式 $db_proxy = new ExtendProxy(); $db_proxy->getUserName(1); $db_proxy->setUserName(29,"xiaobudiu");Extend/Proxy.php
query("select name from user where id =$id limit 1"); } function setUserName($id, $name) { $db = Factory::getDatabase("master"); $db->query("update user set name = $name where id =$id limit 1"); } }Extend/Factory.php
config["database"]["slave"]; $db_conf = $slaves[array_rand($slaves)]; } else { $db_conf = Application::getInstance()->config["database"][$id]; } //注冊(cè)樹模式存儲(chǔ)及獲取對(duì)象 $db = Register::get($key); if (!$db) { $db = new DatabaseMySQLi(); $db->connect($db_conf["host"], $db_conf["user"], $db_conf["password"], $db_conf["dbname"]); Register::set($key, $db); } return $db; } }Extend/Application.php
base_dir = $base_dir; $this->config = new Config($base_dir."/configs"); } static function getInstance($base_dir = "") { if (empty(self::$instance)) { self::$instance = new self($base_dir); } return self::$instance; } }Extend/Config.php
path = $path; } function offsetGet($key) { if (empty($this->configs[$key])) { $file_path = $this->path."/".$key.".php"; $config = require $file_path; $this->configs[$key] = $config; } return $this->configs[$key]; } function offsetSet($key, $value) { throw new Exception("cannot write config file."); } function offsetExists($key) { return isset($this->configs[$key]); } function offsetUnset($key) { unset($this->configs[$key]); } }configs/database.php
array( "type" => "MySQL", "host" => "127.0.0.1", "user" => "root", "password" => "123456", "dbname" => "test", ), "slave" => array( "slave1" => array( "type" => "MySQL", "host" => "127.0.0.1", "user" => "root", "password" => "123456", "dbname" => "test", ), "slave2" => array( "type" => "MySQL", "host" => "127.0.0.1", "user" => "root", "password" => "123456", "dbname" => "test", ), ), ); return $config;關(guān)于php代理模式文章 https://segmentfault.com/a/11...
五、其余設(shè)計(jì)模式以及總結(jié)文章接:
https://segmentfault.com/a/11...
https://segmentfault.com/a/11...
?
六、面向?qū)ο缶幊痰幕驹瓌t1、單一職責(zé)原則:一個(gè)類只需要做好一件事情。不要使用一個(gè)類完成很多功能,而應(yīng)該拆分成更多更小的類。
2、開放封閉原則:一個(gè)類寫好之后,應(yīng)該是可擴(kuò)展而不可修改的。
3、依賴倒置原則:一個(gè)類不應(yīng)該強(qiáng)依賴另外一個(gè)類,每個(gè)類對(duì)于另外一個(gè)類都是可替換的。
4、配置化原則:盡量使用配置,而不是硬編碼。
5、面向接口編程原則:只需要關(guān)心某個(gè)類提供了哪些接口,而不需要關(guān)心他的實(shí)現(xiàn)。
?
七、自動(dòng)加載配置類文件1、php中使用ArrayAccess實(shí)現(xiàn)配置文件的加載(使得程序可以以數(shù)組的方式進(jìn)行讀取配置)
(1)定義Config.php,繼承php自帶的ArrayAccess接口,并實(shí)現(xiàn)相應(yīng)的方法,用于讀取和設(shè)置配置
Extend/Config.php
path = $path; } function offsetGet($key) { if (empty($this->configs[$key])) { $file_path = $this->path."/".$key.".php"; $config = require $file_path; $this->configs[$key] = $config; } return $this->configs[$key]; } function offsetSet($key, $value) { throw new Exception("cannot write config file."); } function offsetExists($key) { return isset($this->configs[$key]); } function offsetUnset($key) { unset($this->configs[$key]); } }(2)configs/database.php
array( "type" => "MySQL", "host" => "127.0.0.1", "user" => "root", "password" => "123456", "dbname" => "test", ), "slave" => array( "slave1" => array( "type" => "MySQL", "host" => "127.0.0.1", "user" => "root", "password" => "123456", "dbname" => "test", ), "slave2" => array( "type" => "MySQL", "host" => "127.0.0.1", "user" => "root", "password" => "123456", "dbname" => "test", ), ), ); return $config;(3)讀取配置
到此,就可以在程序中隨心所欲的加載配置文件了。
2、在工廠方法中讀取配置,生成可配置化的對(duì)象Extend/Factory.php
config["database"]["slave"]; $db_conf = $slaves[array_rand($slaves)]; } else { $db_conf = Application::getInstance()->config["database"][$id]; } //注冊(cè)樹模式存儲(chǔ)及獲取對(duì)象 $db = Register::get($key); if (!$db) { $db = new DatabaseMySQLi(); $db->connect($db_conf["host"], $db_conf["user"], $db_conf["password"], $db_conf["dbname"]); Register::set($key, $db); } return $db; } }Extend/Application.php
base_dir = $base_dir; $this->config = new Config($base_dir."/configs"); } static function getInstance($base_dir = "") { if (empty(self::$instance)) { self::$instance = new self($base_dir); } return self::$instance; } }Extend/Config.php
path = $path; } function offsetGet($key) { if (empty($this->configs[$key])) { $file_path = $this->path."/".$key.".php"; $config = require $file_path; $this->configs[$key] = $config; } return $this->configs[$key]; } function offsetSet($key, $value) { throw new Exception("cannot write config file."); } function offsetExists($key) { return isset($this->configs[$key]); } function offsetUnset($key) { unset($this->configs[$key]); } }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/29977.html
摘要:下面來看主要內(nèi)容爆款面試寶典目錄總覽面試前的準(zhǔn)備工作面試就是雙方互相試探的過程,拋去技術(shù)面不談,面試前簡(jiǎn)歷自我介紹,以及跟對(duì)線細(xì)節(jié)一定要提前準(zhǔn)備好基礎(chǔ)技術(shù)基礎(chǔ)集合多線程框架橫向技術(shù)數(shù)據(jù)庫(kù)消息中間件網(wǎng)絡(luò)設(shè)計(jì)模式 ???? ? ?為了幫大家解決這一問題,LZ今天就把今年金三銀四幫我斬獲了8家大廠...
摘要:假如我們先告訴網(wǎng)關(guān)或服務(wù)注冊(cè)中心我們要下線,等對(duì)方完成服務(wù)摘除操作再中止進(jìn)程,那不會(huì)有任何流量受到影響這是優(yōu)雅停止,將單個(gè)組件的啟停對(duì)整個(gè)系統(tǒng)影響最小化。與此同時(shí),會(huì)將從對(duì)應(yīng)的上摘除。 作者:吳葉磊 一直以來我對(duì)優(yōu)雅地停止 Pod 這件事理解得很單純:不就利用是?PreStop hook?做優(yōu)雅退出嗎?但最近發(fā)現(xiàn)很多場(chǎng)景下 PreStop Hook 并不能很好地完成需求,這篇文章就簡(jiǎn)單...
摘要:假如我們先告訴網(wǎng)關(guān)或服務(wù)注冊(cè)中心我們要下線,等對(duì)方完成服務(wù)摘除操作再中止進(jìn)程,那不會(huì)有任何流量受到影響這是優(yōu)雅停止,將單個(gè)組件的啟停對(duì)整個(gè)系統(tǒng)影響最小化。與此同時(shí),會(huì)將從對(duì)應(yīng)的上摘除。 作者:吳葉磊 一直以來我對(duì)優(yōu)雅地停止 Pod 這件事理解得很單純:不就利用是?PreStop hook?做優(yōu)雅退出嗎?但最近發(fā)現(xiàn)很多場(chǎng)景下 PreStop Hook 并不能很好地完成需求,這篇文章就簡(jiǎn)單...
閱讀 1439·2021-11-11 16:54
閱讀 9319·2021-11-02 14:44
閱讀 2371·2021-10-22 09:53
閱讀 3259·2019-08-30 11:18
閱讀 1951·2019-08-29 13:29
閱讀 2003·2019-08-27 10:58
閱讀 1623·2019-08-26 11:38
閱讀 3518·2019-08-26 10:31