国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 語言 > PHP > 正文

PHP中常用的三種設計模式詳解【單例模式、工廠模式、觀察者模式】

2024-05-05 00:09:37
字體:
供稿:網(wǎng)友

本文實例講述了PHP中常用的三種設計模式。分享給大家供大家參考,具體如下:

PHP中常用的三種設計模式:單例模式、工廠模式、觀察者模式

1.單例模式

為何要使用PHP單例模式?

多數(shù)人都是從單例模式的字面上的意思來理解它的用途, 認為這是對系統(tǒng)資源的節(jié)省, 可以避免重復實例化, 是一種”計劃生育”. 而PHP每次執(zhí)行完頁面都是會從內(nèi)存中清理掉所有的資源. 因而PHP中的單例實際每次運行都是需要重新實例化的, 這樣就失去了單例重復實例化的意義了. 單單從這個方面來說, PHP的單例的確有點讓各位失望. 但是單例僅僅只有這個功能和應用嗎? 答案是否定的。

  1. php的應用主要在于數(shù)據(jù)庫應用, 所以一個應用中會存在大量的數(shù)據(jù)庫操作, 在使用面向?qū)ο蟮姆绞介_發(fā)時(廢話), 如果使用單例模式, 則可以避免大量的new 操作消耗的資源。
  2. 如果系統(tǒng)中需要有一個類來全局控制某些配置信息, 那么使用單例模式可以很方便的實現(xiàn). 這個可以參看zend Framework的FrontController部分。
  3. 在一次頁面請求中, 便于進行調(diào)試, 因為所有的代碼(例如數(shù)據(jù)庫操作類db)都集中在一個類中, 我們可以在類中設置鉤子, 輸出日志,從而避免到處var_dump, echo。

一個單例類應包括以下幾點:

和普通類不同,單例類不能被直接實例化,只能是由自身實例化。因此,要獲得這樣的限制效果,構(gòu)造函數(shù)必須標記為private

要讓單例類不被直接實例化而能起到作用,就必須為其提供這樣的一個實例。因此,就必須要讓單例類擁有一個能保存類的實例的私有靜態(tài)成員變量和對應的一個能訪問到實例的公共靜態(tài)方法。

在PHP中,為防止對單例類對象的克隆來打破單例類的上述實現(xiàn)形式,通常還為其提供一個空的私有__clone()方法。

對于一個類的對象,如果使用“clone運算符”,就會復制出一個和當前對象完全一樣的新對象出來,并且,此時還會自動調(diào)用該類的魔術(shù)方法:__clone()(只要該類中有該方法)。

則要實現(xiàn)單例類,就應該對這個單例類的對象“禁止克隆”,用private來修飾__clone()來實現(xiàn)禁止克隆,具體可參考單例類的加強:禁止克隆

單例模式的例子:

<?php/*** 設計模式之單例模式* $instance必須聲明為靜態(tài)的私有變量* 構(gòu)造函數(shù)和析構(gòu)函數(shù)必須聲明為私有,防止外部程序new* 類從而失去單例模式的意義* getInstance()方法必須設置為公有的,必須調(diào)用此方法* 以返回實例的一個引用* ::操作符只能訪問靜態(tài)變量和靜態(tài)函數(shù)* new對象都會消耗內(nèi)存* 使用場景:最常用的地方是數(shù)據(jù)庫連接。* 使用單例模式生成一個對象后,* 該對象可以被其它眾多對象所使用。*/class SingetonBasic {private static $instance; //靜態(tài)變量要私有化,防止類外修改// other vars..private function __construct() {  //構(gòu)造函數(shù)私有化,類外不能直接新建對象  // do construct..}private function __clone() {}  //在__clone()前用private修飾,用來禁止克隆public static function getInstance() { //公共的靜態(tài)方法,public——外部的接口,static——不使用對象而是通過類名訪問  if (!(self::$instance instanceof self)) { //私有靜態(tài)變量$instance為空    self::$instance = new self(); //新建為自身的對象,并賦值給私有變量$instance  }  return self::$instance; //返回私有變量$instance}// other functions..}$a = SingetonBasic::getInstance();$b = SingetonBasic::getInstance();var_dump($a === $b);  //結(jié)果為:boolean true//?>
<?php/** * php單例,單例模式為何只能實例化一次*/class Example{  // 保存類實例在此屬性中  private static $instance;  // 構(gòu)造方法聲明為private,防止直接創(chuàng)建對象  private function __construct(){    echo 'I am constructed';  }  // singleton 方法  public static function singleton(){    if (!isset(self::$instance)) {//判斷是否以前創(chuàng)建了當前類的實例      $c = __CLASS__;//獲取類名      self::$instance = new $c;//如果沒有創(chuàng)建,實例化當前類,這里實現(xiàn)類只實例化一次    }    return self::$instance;//返回類的實例  }  // Example類中的普通方法  public function bark(){    echo 'Woof!';  }  // 阻止用戶復制對象實例  public function __clone(){    trigger_error('Clone is not allowed.', E_USER_ERROR);  }}// 這個寫法會出錯,因為構(gòu)造方法被聲明為private$test = new Example;// 下面將得到Example類的單例對象$test = Example::singleton();$test->bark();// 下面將得到Example類的單例對象$test = Example::singleton();$test->bark();// 復制對象將導致一個E_USER_ERROR.$test_clone = clone $test;?>

 

2. 工廠模式

工廠模式在于可以根據(jù)輸入?yún)?shù)或者應用程序配置的不同來創(chuàng)建一種專門用來實現(xiàn)化并返回其它類的實例的類。

工廠模式的例子:

<?phpclass FactoryBasic {  public static function create($config) {  }}

比如這里是一個描述形狀對象的工廠,它希望根據(jù)傳入的參數(shù)個數(shù)不同來創(chuàng)建不同的形狀。

<?php// 定義形狀的公共功能:獲取周長和面積。interface IShape {  function getCircum();  function getArea();}// 定義矩形類class Rectangle implements IShape {  private $width, $height;  public function __construct($width, $height) {    $this->width = $width;    $this->height = $height;  }  public function getCircum() {    return 2 * ($this->width + $this->height);  }  public function getArea() {    return $this->width * $this->height;  }}// 定義圓類class Circle implements IShape {  private $radii;  public function __construct($radii) {    $this->radii = $radii;  }  public function getCircum() {    return 2 * M_PI * $this->radii;  }  public function getArea() {    return M_PI * pow($this->radii, 2);  }}// 根據(jù)傳入的參數(shù)個數(shù)不同來創(chuàng)建不同的形狀。class FactoryShape {  public static function create() {    switch (func_num_args()) {      case 1:      return new Circle(func_get_arg(0));      break;      case 2:      return new Rectangle(func_get_arg(0), func_get_arg(1));      break;    }  }}// 矩形對象$c = FactoryShape::create(4, 2);var_dump($c->getArea());// 圓對象$o = FactoryShape::create(2);var_dump($o->getArea());

使用工廠模式使得在調(diào)用方法時變得更容易,因為它只有一個類和一個方法,若沒有使用工廠模式,則要在調(diào)用時決定應該調(diào)用哪個類和哪個方法;使用工廠模式還使得未來對應用程序做改變時更加容易,比如要增加一種形狀的支持,只需要修改工廠類中的create()一個方法,而沒有使用工廠模式,則要修改調(diào)用形狀的代碼塊。

3. 觀察者模式

觀察者模式為您提供了避免組件之間緊密耦合的另一種方法。該模式非常簡單:一個對象通過添加一個方法(該方法允許另一個對象,即觀察者注冊自己)使本身變得可觀察。當可觀察的對象更改時,它會將消息發(fā)送到已注冊的觀察者。這些觀察者使用該信息執(zhí)行的操作與可觀察的對象無關。結(jié)果是對象可以相互對話,而不必了解原因。

一個簡單的示例:當聽眾在收聽電臺時(即電臺加入一個新聽眾),它將發(fā)送出一條提示消息,通過發(fā)送消息的日志觀察者可以觀察這些消息。

<?php// 觀察者接口interface IObserver {  function onListen($sender, $args);  function getName();}// 可被觀察接口interface IObservable {  function addObserver($observer);  function removeObserver($observer_name);}// 觀察者類abstract class Observer implements IObserver {  protected $name;  public function getName() {    return $this->name;  }}// 可被觀察類class Observable implements IObservable {  protected $observers = array();  public function addObserver($observer) {    if (!($observer instanceof IObserver)) {      return;    }    $this->observers[] = $observer;  }  public function removeObserver($observer_name) {    foreach ($this->observers as $index => $observer) {      if ($observer->getName() === $observer_name) {        array_splice($this->observers, $index, 1);        return;      }    }  }}// 模擬一個可以被觀察的類:RadioStationclass RadioStation extends Observable {  public function addListener($listener) {    foreach ($this->observers as $observer) {      $observer->onListen($this, $listener);    }  }}// 模擬一個觀察者類class RadioStationLogger extends Observer {  protected $name = 'logger';  public function onListen($sender, $args) {    echo $args, ' join the radiostation.<br/>';  }}// 模擬另外一個觀察者類class OtherObserver extends Observer {  protected $name = 'other';  public function onListen($sender, $args) {    echo 'other observer..<br/>';  }}$rs = new RadioStation();// 注入觀察者$rs->addObserver(new RadioStationLogger());$rs->addObserver(new OtherObserver());// 移除觀察者$rs->removeObserver('other');// 可以看到觀察到的信息$rs->addListener('cctv');?>

希望本文所述對大家PHP程序設計有所幫助。


注:相關教程知識閱讀請移步到PHP教程頻道。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表

圖片精選

主站蜘蛛池模板: 武定县| 独山县| 收藏| 唐河县| 丹寨县| 桑植县| 隆尧县| 嘉祥县| 东乌珠穆沁旗| 根河市| 洛隆县| 济源市| 茶陵县| 锦州市| 中宁县| 汉源县| 莱州市| 兰坪| 松潘县| 资讯 | 新密市| 佛教| 九江市| 平南县| 蒙城县| 那曲县| 杭州市| 焦作市| 阳新县| 德庆县| 景泰县| 肥乡县| 东丰县| 平泉县| 故城县| 邵东县| 防城港市| 靖边县| 肃宁县| 象山县| 建湖县|