溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

PHP框架之設計模式的示例分析

發(fā)布時間:2021-08-23 10:54:09 來源:億速云 閱讀:146 作者:小新 欄目:開發(fā)技術

小編給大家分享一下PHP框架之設計模式的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

為什么要使用設計模式?

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

感興趣的讀者可以閱讀《Design Patterns: Elements of Reusable Object-Oriented Software》,四位作者(Gang of Four)在書中列舉了業(yè)界聞名的23種設計模式。

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

單例模式(singleton)

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

這里,我們改寫上一章節(jié)的MySQL

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類,我們不再寫

$db=new MySQL();

而是這樣:

$db=MySQL::getInstance();

因為只有getInstance這個靜態(tài)函數(shù),才能保證只調用一次MySQL類的構造函數(shù)。

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

外觀模式(Facade)

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

class ServiceProvider{
	public function Write($arg){
		echo $arg;
	}
}

這個類只有一個Write方法,就是把參數(shù)打印出來

然后定義一個Facade類

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

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

我們再寫一個Facade子類

class MyFacade extends Facade{
	public static function getFacadeAccessor(){
		return ServiceProvider::class;
	}
}

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

抽象工廠(Factory)

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

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

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

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

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

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

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

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

我們定義一個服務容器類

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方法就是用關聯(lián)數(shù)組把字符串和構造函數(shù)做綁定。

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

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框架之設計模式的示例分析”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業(yè)資訊頻道!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

php
AI