设计模式可以大略理解为我们以前所学的一些所谓的"算法":

它是古人针对某些常规任务所总结出来的"一样平常化良好做法", 并被很多人所推崇并利用。

设计模式有很多种(大约几十种):每一种设计模式, 常日都是针对某种特定环境的需求。

php设计师PHP 设计模式 Angular

工厂类:

观点:

便是设计一个类, 该类的目的(浸染)是能够"天生"工具--只要调用该类的时候, 传入一个须要生产的工具的类名, 就可以"立即"生产出该类的一个工具。

一个基本观点演示:

class Factory{ static function Shengchan( $className ){ $obj = new $className(); return $obj; }}class A{}class B{}$o1 = Factory::Shengchan("A");$o2 = Factory::Shengchan("B");var_dump($o1);echo "<br />";var_dump($o2);

显示结果:object(A)#1 (0) { }object(B)#2 (0) { }

可见:工厂类, 便是专学临盆工具的。
给其一个类, 则该工厂类就会生产出一个该类的工具。

在实际运用中, 不可能利用一个工厂类, 就可以生产所有工具。

常日, 一个工厂类, 每每是用于生产某一个方面的类的工具---即这些类属于"同一范畴的类"。

比如:

class ImgFactory{ static function GetInstance( $fileName ){//Instance便是“实例”的意思。
$houzhui = strrchr($fileName, &#39;.'); //取得文件的后缀,//这里含“.” $houzhui = strtolower($houzhui); if( $houzhui == '.jpg'){ $obj = new jpg(); } else if( $houzhui == '.gif'){ $obj = new gif(); } else if( $houzhui == '.png'){ $obj = new png(); } else{ $obj = null; //这里可以去“报错” } return $obj; }}class IMG{}class jpg extends IMG{};class gif extends IMG{};class png extends IMG{};$file1 = './abc.jpg'; //代表用户上传的图片,可能是其他类型$o1 = ImgFactory::GetInstance($file1);if(isset($o1) ){//利用该工具$o1做下一步的事情。
}

实例3:

<?phpheader("Content-type: text/html; charset=utf-8");class factory{ public static function getObj($className){ self::autoload($className); $obj = new $className(); return $obj; } private static function autoload($className){ if(is_file("{$className}.class.php")){ include "{$className}.class.php"; }else{ } }}$obj = factory::getObj('DB');var_dump($obj);?>

单例模式

"例":便是"实例"的意思;

"单例", 便是只有一个工具—--即一个类只能生产出一个工具来, 有利于节省资源。

即, 我们的目标是:设计一个类, 该类"无论如何", 都只能创建出一个工具!

class Single{ public $p1 = 1; static $instance = null; //目的:用于存储本类的一个工具 private function __construct(){ //私有化布局方法, 目的是让该类不能通过new创建工具 } private function __clone(){} //私有化克隆方法, 目的是让该类不能通过克隆的方法创建工具 static function GetOne(){ if(!self::$instance instanceof self){//A中还没有生产过工具 self::$instance = new self(); return self::$instance; } else{ return self::$instance;//直接返复临盆过的工具 } }}//$o1 = new Single(); //私有化布局方法后,此行出错//$o2 = new Single(); //即此时无法多次new工具出来。
$o1 = Single::GetOne();$o2 = Single::GetOne();$o2->p1 = 11;var_dump($o1);echo "<br />";var_dump($o2);

显示结果:object(Single)#1 (1) { ["p1"]=> int(11) }object(Single)#1 (1) { ["p1"]=> int(11) }

实例一个单例工具的关键点为:

(1)将类的布局方法私有化

(2)定义一个静态属性, 由该静态属性来"存储"创建出来的该类的工具;

(3)设计一个静态方法, 由该静态方法来供应工具的创建事情。

在该类中, 通过类的静态属性的判断, 来决定是否须要创建一个工具:

i.如果该静态属性中没有存储该工具, 则创建一个, 并存入该静态属性, 然后返回该工具;

ii.如果该静态属性中, 已经存在该工具, 则直接返回该工具。

单例工厂类

设计一个类, 该类能"生产"某些类的工具, 且只能生产出该类工具的"一个工具"——单例。

Factory.class.php

<?php//工厂类//目的:用于实现模型类的单例://即要获取某个模型的单例,只要通过本工厂类就可以了!
class Factory{static function GetObject($ModelName){//$ModelName是一个模型类的类名,比如"UserModel"static $arr = array(); //这里用的是一个方法(函数)中的静态变量,也可以用类的静态属性//if( isset($arr[$ModelName]) && !($arr[$ModelName] instanceof $ModelName) ){//还不存在该模型类的实例if( isset($arr[$ModelName])== false || !($arr[$ModelName] instanceof $ModelName) ){//还不存在该模型类的实例//如果不存在,或,“虽然存在”,但不是该类的实例$arr[$ModelName] = new $ModelName();}return $arr[$ModelName];}}class A{}$obj1 = Factory::GetObject("A");var_dump($obj1); //object(A)#1 (0) { }//$obj1 = Factory::GetObject("UserModel");

实例:数据库操作类

<?php//定义一个mysql数据库工具类,该类可以在实例化的时候//自动连接上mysql数据库://自然,在实例化的时候,须要连接mysql数据的6个基本参数://利用单例模式//在序列化和反序列化时调用魔术方法__sleep和__wakeup() 由于反序列化不会自动调用函数class MySQLDB{ private $conn ; private $_host; private $_port; private $_username; private $_password; private $_charset; private $_dbname; private static $instance = null; //用于存储单例工具 private function __construct($config){ //先将6个基本连接数据存起来 $this->_host = isset($config['host']) ? $config['host'] : "localhost"; //如果不存在,利用默认值localhost $this->_port = isset($config['port']) ? $config['port'] : '3306'; $this->_username = isset($config['username']) ? $config['username'] : 'root'; $this->_password = isset($config['password']) ? $config['password'] : '1234abcd'; $this->_charset = isset($config['charset']) ? $config['charset'] : 'utf8'; $this->_dbname = isset($config['dbname']) ? $config['dbname'] : 'test'; $this->connect(); //mysql_query("set names $charset", $this->conn); //设置当前连接的连接编码为 $charset //mysql_query("use $dbname", $this->conn); //设置当前要操作的数据库为 $dbname //更一样平常化:将上述两行设置编码和数据库的事情,“搬”到各自单独的方法中: $this->SetCharset($this->_charset); $this->SetDB($this->_dbname); } function connect(){ $this->conn = mysql_connect("{$this->_host}:{$this->_port}",$this->_username, $this->_password) or die("连接失落败");//连接成功后,将连接资源给自身的属性 } //单例设计的第4步:禁止克隆 private function __clone(){ } static function GetInstance($cfg){ //if( !isset(self::$instance)){//改造为下一行更严谨的判断: if( !(self::$instance instanceof self) ){ self::$instance = new self($cfg); } return self::$instance; } function SetCharset($charset){ mysql_query("set names $charset", $this->conn); } function SetDB($db){ mysql_query("use $db", $this->conn); } function close(){ mysql_close($this->conn); } //方法目的:实行增编削语句: function exec( $sql ){ $result = $this->query($sql); //此时得到的是true return $result; } //方法目的:实行查询语句返回一行数据 function GetOneRow( $sql ){ $result = $this->query($sql); //此时得到的是结果集 if(mysql_num_rows($result) > 0){ $arr = mysql_fetch_array($result);//取得结果集的一行 } else{ $arr = array(); } //此时 $arr 是一个数组 $result = null; //销毁了该结果集 return $arr; } //方法目的:实行查询语句返回多行数据 function GetAllRow( $sql ){ $result = $this->query($sql);//此时得到的是结果集,而且是多行!
$arrList = array(); if(mysql_num_rows($result) > 0){ while($arr = mysql_fetch_array( $result )){ //$arr也是一个一维数组(个中包括了“一整行”的数据) //其是放在数组中,下标便是该select语句的字段名 $arrList[] = $arr; //此时,$arrList实在是一个“二维数组” } } $result = null; //销毁了该结果集 return $arrList; } //方法目的:实行查询语句返回一个数据 function GetOneData( $sql ){ $result = $this->query($sql);//此时得到的是结果集,但此时是“一行一列” if(mysql_num_rows($result) > 0){ $arr = mysql_fetch_row( $result ); //此为一个数组 $data = $arr[0]; } else{ $data = null; } $result = null; //销毁了该结果集 return $data; } function query($sql){ $result = mysql_query($sql, $this->conn); if($result === false){ echo "<br />实行失落败,返回缺点信息:" . mysql_error(); echo "<br />出错语句:" . $sql; echo "<br />出错文件:" . $_SERVER['PHP_SELF'];//当前网页文件 die(); } return $result; } / 防止SQL-injection @param string $str 待转义的字符串 @return string 转义处理后的 / public function escapeString($str) { return mysql_real_escape_string($str); } //序列化时,会先调用该方法:我们可以在此清理一些资源,并返回要进行序列化的属性 function __sleep(){ //这里也可以去做别的事情,比如常日可以去清理一些不再须要的“资源”。
//返回一个数组,个中存储想要进行序列化的属性的名字 return array('_host','_port','_username','_password','_charset','_dbname'); } //反序列化时,会先调用该方法,我们可以对该工具的内部进行某些预先操作(比如连库) function __wakeup(){ $this->connect(); //这里是去做连接数据库事情!
由于反序列化时不会自动调用函数 $this->SetCharset($this->_charset); $this->SetDB($this->_dbname); } //接下来,还须要让该工具实现单例。
//还须要让该工具能够完成以下事情:实行增编削语句, //实行查询语句,并根据查询的结果数据,返回:一行数据,多行数据,一个数据。
}?>

利用方法:

<?phpclass Model{ private $config ; //DAO:数据访问工具(Data Access Object) protected $_dao; //用于存储mysqldb的工具类工具 function __construct(){ $this->config = array( 'host'=>'localhost', 'port'=>'3306', 'username'=>'root', 'password'=>'123', 'charset'=>'utf8', 'dbname'=>'php36' ); require_once './MySQLDB.class.php'; $this->_dao = MySQLDB::GetInstance( $this->config ); }}