程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> PHP十二種設計模式

PHP十二種設計模式

編輯:關於PHP編程

PHP十二種設計模式


PSR-0規范的設計基礎
1.全部使用命名空間
2.所有php文件必須自動載入,不能有include/require
spl_autoload_register
3.單一入口模式




1.三種基本的設計模式
工廠模式
用一個工廠方法去替換掉一個new


class Factory{

static function createDatabase(){
$db = new Database;
return $db;
}
}
使用的時候就可以用 $db = Factory::createDatabase();




單例模式
class Database{
private $db;


private function __construct(){
//這裡可以寫連接數據庫
}


static function getInstance(){
if(self::$db){
return self::$db;
}else{
self::$db=new self()
return self::$db;//private可以自身調用
}
}


function where(){




}


}


如果是工廠加單例模式
class Factory{

static function createDatabase(){
$db = Database::getInstance();
return $db;
}
}


注冊器(樹)模式
class Register{
protected static $object;
static function set($alias,$object){
self::$object[$alias]=$object;


}
static function get($name)
{
return self::$object[$name];
}
function _unset($alias){
unset(self::$object[$alias]);
}
}
跟工廠方法結合
class Factory{

static function createDatabase(){
$db = Database::getInstance();
Register::set('db1',$db);
return $db;
}
}
索引直接調用
$db = Register::get('db1');


適配器模式
1.適配器模式,可以將截然不同的函數接口封裝成統一的API
2.實際應用舉例,PHP的數據庫操作有mysql,mysqli,pdo3種,可以用適配器模式
統一成一致,類似的場景還有cache適配器,將memcache,redis,file,apc等不同的緩存函數,統一成一致,
比如說有一個Database.php裡面有一個接口
interface IDatabase
{
function connect($host,$user,$pwd,$dbname);
function query($sql);
function close();
}


再下面有三個類
class mysql implements IDatabase{
private $con;
function connect($host,$user,$pwd,$dbname){
$this->con = mysql_connect($host,$user,$pwd);
mysql_select_db($dbname,$this->con);
}
function query($sql){
return mysql_query($sql,$this->con);
}
function close(){
return mysql_close($this->con);
}
}


class mysqli implements IDatabase{
protected $con;
function connect($host,$user,$pwd,$dbname)
{
$this->con = mysqli_connect($host,$user,$pwd,$dbname);
}
function query($sql)
{
return mysqli_query($this->con,$sql);
}
function close()
{
return mysqli_close($this->con);
}
}


class PDO implements IDatabase{
protected $con;
function connect($host,$user,$pwd.$dbname)
{
$con = new \PDO("mysql:host=$host;dbname=$dbname",$user,$pwd);
$this->con=$con;
}
function query($sql){
return $this->con->query($sql);
}
function close(){
unset($this->con);
}
}
這樣我們調用的時候
$db = new mysql();或new mysqli();或new PDO();
$db->connect('127.0.0.1','root','root');
$db->query();
$db->close();


策略模式
將一組特定的行為和算法封裝成類,以適應某些特定的上下文環境,這種模式就是策略模式
實際應用距離,假如一個電商系統的網站系統,針對男性女性用戶要各自跳轉到不同的商品類別
首先聲明一個策略的接口文件
interface UserStrategy{
function showAd();
function showcategory();
}


//第一個策略 針對女性用戶
class femaleUserStrategy implements UserStrategy{
function showAd(){
echo '2014新款女裝';
}
function showCategory()
{
echo '女裝';
}
}
//第二個策略,針對於男性用戶
class maleUserStrategy implements UserStrategy{
function showAd(){
echo '2014新款男裝';
}
function showCategory()
{
echo '男裝';
}
}
//如果有一個page類
class page{
protected $strategy;
function index(){
$this->strategy->showAd();
$this->strategy->showCategory();
}


function setStrategy(\UserStrategt $strategy){
$this->strategy=$strategy;
}
}
$page = new Page();
if(isset($_GET['female'])){
$strategy = new femaleUserStrategy();
}else{
$strategy = new maleUserStrategy();
}
$page->setStrategy($strategy);
$page->index();
從一個硬編碼到解耦的模式


數據對象映射模式
數據對象映射模式,是將對象和數據存儲映射起來,對一個
對象的操作會映射為對數據存儲的操作。
在代碼中實現數據對象映射模式,我們將實現一個ORM類,將復雜的sql語句映射成對象屬性的操作
class User{
public $id;
public $name;
public $mobile;
public $regtime;
protected $db;
function __construct($id){
//先取數據
$this->db = new mysql();
$this->db->connect('xxxxx'xxxx);
$res = $this->db->query('select * from XXX where id = {$id}');
$data = $res->fetch_assoc();


$this->id=$data['id'];
$this->name=$data['name'];
$this->mobile=$data['mobile'];
$this->regtime=$data['regtime'];
return $res;
}


function __destruct(){
//可以作為修改使用
$this->db->query('update xx set name={$this->name} mobile={$this->mobile}XXXXX where id = {$this->id}');
}
}


$user = new User(1);//1對應數據庫中id為一
$user->mobile = '155555555';
$user->name='test';
$user->regtime=time();
//在這裡沒有sql語句.只有對對象的操作


綜合運用(工廠模式,注冊器模式,適配器模式)



觀察者模式
1.觀察者模式,當一個對象狀態發生改變時,依賴他的對象全部會收到通知,並自動更新。
2.場景:一個事件發生後,要執行一連串更新操作,傳統的編程方式,就
是在事件的代碼之後直接加入處理邏輯,當更新的邏輯增多之後,代碼會變得難以維護,這種方式是耦合的,侵入式的,
增加心的邏輯需要修改事件主體的代碼
3.觀察者模式實現了低耦合,非侵入式的通知更新機制。
demo
class Event{
function trigger(){
echo "Event";//表示事件發生了


//開始寫更新邏輯了
echo '邏輯1';

echo '邏輯2';


echo '邏輯3';


}
}


$event = new Event();//傳統的方式是耦合的,侵入式的,
//必須要改源碼,所以我們定義一個觀察者模式
demo
//在來一個接口
//先來一個基類抽象類
abstract class EventGenerator{
private $observers = array();
function addObserver(Observer$observer){
$this->obervers[]=$oberver;
}
function notify(){
foreach($this->obervers as $observer)
{
$observer->updata();
}
}
}
interface Oberver{
function update($event_info = null);
}
//所以說這個時候我們需要Event類繼承這個基類
class Event extends EventGenerator{
function trigger(){
echo "Event";//表示事件發生了
$this->notify();
}
}


class Observer1 implements Observer{
function updata($event_info=null)
{
echo "邏輯一";
}
}


class Oberver2 implements Oberver{
function updata($event_info=null)
{
echo "邏輯二";
}
}




原型模式
1.與工廠模式作用類似,都是用來創建對象
2.與工廠模式的實現不同,原型模式先創建好一個原型
對象,然後通過clone原型對象來創建新的對象,這樣就免去了類
創建時重復的初始化操作
3.原型模式適合於大對象的創建,創建一個大對象需要很大的開銷,如果每次new就會消耗很大,
原型模式僅僅拷貝內存即可。
假如有一個畫布類。new很復雜
我又想使用他兩次
這樣我們就可以用原型模式解決new的問題,用clone替代new
初始化之後直接clone即可。


裝飾器模式
1.裝飾器模式,可以動態的添加修改類的功能。
2.一個類提供了一項功能,如果要在修改並添加額外的功能,傳統的
編程模式,需要寫一個子類繼承他,並重新實現類的方法。
3.使用裝飾器模式,僅需在運行時添加一個裝飾器對象即可實現,可以實現最大的靈活性
如果我們有一個畫布類。只能打印一個正方形,假如我們想要添加一個顏色
一般是寫一個子類,繼承那個畫布類。
重寫產生畫布的方法。那我們如果要增加很多功能呢?
是不是要重寫很多類?
下面我們用裝飾器模式解決這個問題
首先我們先聲明一個畫布的裝飾器的接口
interface DrawDecorator{
function beforeDraw();
function afterDraw();
}


比如我們要修改畫布類的draw()方法
所以我們在draw()方法中調用
function draw(){
$this->beforeDraw();
//這裡是原來代碼的內容
$this->afterDraw();
}
再在畫布類中添加一個protected $decorators[]=array();
在添加一個方法,用來接收裝飾器接口
function addDecorator(DrawDecorator $decorator){
$this->decorators[]=$decorator;
}
再添加兩個調用裝飾器的方法
function beforeDraw(){
foreach($this->decorators as $decorator)
{
$decorator->beforeDraw();
}
}


function afterDraw(){
//進行反轉,後進先出
$decorators = array_reverse($this->decorators);
foreach($decorators as $decorator)
{
$decorator->afterDraw();
}
}


我們有一個顏色裝飾器
class ColorDrawDecorator implements DrawDecorator{
protected $color;
function __construct($color='red')
{
$this->color= $color;
}
function beforDraw()
{
echo "color};'>";
}
function afterDraw()
{
echo ""
}
}
在這裡就不用去繼承去實現了
$a = new canvas();//實例化畫布類
$a -> init();//初始化
$a -> addDecorator(new colorDrawDecorator('green'));//添加一個顏色的裝飾器類
迭代器模式
1.迭代器模式,在不需要了解內部實現的前提下,遍歷yige
聚合對象的內部元素
2.相比傳統的編程模式,迭代器模式可以隱藏遍歷元素的所需的操作
比如遍歷一個數據庫,然後拿到所有對象
class Alluser implements Iterator{
protected $ids;
protected $index;//迭代器當前位置
protected $data=array();
//Iterator為迭代器接口
fucntion __construct(){
$db = Factory::getDatabase();
$result = $db->query("selecy id from user");
$this->ids = $db->mysql_fetch_assoc($result);
}
function current(){
//獲取當前元素
$id=$this->ids[$this->index]['id'];
return Factory::getUser($id);
}
function next(){
//下一個元素
$this->index ++;
}
function valid()
{
//判斷是否有數據
return $this->index < count($this->ids);
}
function rewind(){
$this->index=0;//第一步到開頭
}
function key(){
//獲取當前索引
return $this->index;
}
}
$users = new Alluser();
foreach ($users as $user)
{
var_dump($user);
}
代理模式
1.在客戶端與實體之間建立一個代理對象(proxy),客戶端對實體進行操作全部委派給代理對象,隱藏實體具體實現細節。
就是寫一個


面向對象編程的基本原則
1.單一職責:一個類,只需要做好一件事情
2.開放封閉:一個類,應該是可擴展的,而不可修改的
3.依賴倒置:一個類,不應該強依賴另外一個類,每個類對於另外一個類都是可替換的
4.配置化:盡可能的使用配置,而不是硬編碼。
5.面向接口編程:只需要關心接口,不需要關心實現。


MVC架構原理
我們先new 一個Config的對象
$config = new Config(__DIR__.'/configs');
$config['controller'];


那麼有一個Config類
class Config implements \ArrayAccess{
//ArrayAccess接口是內置的接口,表示允許數組傳值,其中有要實現四個方法
protected $path;
protected $configs=array();
function __construct($path)
{
$this->path=$path;
}
function offsetGet($key){
//獲取該配置數組文件名key
if(empty($this->configs[$key]))
//如果原配置文件中不存在該數組文件名,那麼就去加載
{
$file_path=$this->path.'/'.$key.'.php';//生成加載路徑
$config = require $file_path;
$this->config[$key]=$config;
}
return $this->configs[$key];


}
function offsetSet($key,$value)
{
//設置數組的key
}
function offsetExists($key)
{ //檢測數組的key是否存在
return isset($this->configs[$key]);
}
function offsetUnset($key)
{ //刪除數組的key

}
}


配置文件比如controller.php
$config = array(
'home'=>array(
'decorator'=>array(
'IMooc\Dectorator\Template',
),
),
);


配置與設計模式
1.PHP中使用ArrayAccess實現配置文件的加載
2.在工廠方法中讀取配置,生成可配置化的對象
3.使用裝飾器模式實現權限驗證,模板渲染,json串化
4.使用觀察者模式實現數據更新事件的一系列更新操作
5.使用代理模式實現數據庫的主從自動切換

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved