PHP中常用的三种设计模式详解【单例模式、工厂模式、观察者模式】

本文实例讲述了PHP中常用的三种设计模式。分享给大家供大家参考,具体如下:

PHP中常用的三种设计模式:单例模式、工厂模式、观察者模式

1.单例模式

为何要使用PHP单例模式?

多数人都是从单例模式的字面上的意思来理解它的用途, 认为这是对系统资源的节省, 可以避免重复实例化, 是一种”计划生育”. 而PHP每次执行完页面都是会从内存中清理掉所有的资源. 因而PHP中的单例实际每次运行都是需要重新实例化的, 这样就失去了单例重复实例化的意义了. 单单从这个方面来说, PHP的单例的确有点让各位失望. 但是单例仅仅只有这个功能和应用吗? 答案是否定的。

  1. php的应用主要在于数据库应用, 所以一个应用中会存在大量的数据库操作, 在使用面向对象的方式开发时(废话), 如果使用单例模式, 则可以避免大量的new 操作消耗的资源。
  2. 如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看zend Framework的FrontController部分。
  3. 在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。

一个单例类应包括以下几点:

和普通类不同,单例类不能被直接实例化,只能是由自身实例化。因此,要获得这样的限制效果,构造函数必须标记为private

要让单例类不被直接实例化而能起到作用,就必须为其提供这样的一个实例。因此,就必须要让单例类拥有一个能保存类的实例的私有静态成员变量和对应的一个能访问到实例的公共静态方法。

在PHP中,为防止对单例类对象的克隆来打破单例类的上述实现形式,通常还为其提供一个空的私有__clone()方法。

对于一个类的对象,如果使用“clone运算符”,就会复制出一个和当前对象完全一样的新对象出来,并且,此时还会自动调用该类的魔术方法:__clone()(只要该类中有该方法)。

则要实现单例类,就应该对这个单例类的对象“禁止克隆”,用private来修饰__clone()来实现禁止克隆,具体可参考单例类的加强:禁止克隆。

单例模式的例子:

<?php
/**
* 设计模式之单例模式
* $instance必须声明为静态的私有变量
* 构造函数和析构函数必须声明为私有,防止外部程序new
* 类从而失去单例模式的意义
* getInstance()方法必须设置为公有的,必须调用此方法
* 以返回实例的一个引用
* ::操作符只能访问静态变量和静态函数
* new对象都会消耗内存
* 使用场景:最常用的地方是数据库连接。
* 使用单例模式生成一个对象后,
* 该对象可以被其它众多对象所使用。
*/
class SingetonBasic {
private static $instance; //静态变量要私有化,防止类外修改
// other vars..
private function __construct() {  //构造函数私有化,类外不能直接新建对象
  // do construct..
}
private function __clone() {}  //在__clone()前用private修饰,用来禁止克隆
public static function getInstance() { //公共的静态方法,public——外部的接口,static——不使用对象而是通过类名访问
  if (!(self::$instance instanceof self)) { //私有静态变量$instance为空
    self::$instance = new self(); //新建为自身的对象,并赋值给私有变量$instance
  }
  return self::$instance; //返回私有变量$instance
}
// other functions..
}
$a = SingetonBasic::getInstance();
$b = SingetonBasic::getInstance();
var_dump($a === $b);  //结果为:boolean true
//?>
<?php
/**
 * php单例,单例模式为何只能实例化一次
*/
class Example{
  // 保存类实例在此属性中
  private static $instance;
  // 构造方法声明为private,防止直接创建对象
  private function __construct(){
    echo 'I am constructed';
  }
  // singleton 方法
  public static function singleton(){
    if (!isset(self::$instance)) {//判断是否以前创建了当前类的实例
      $c = __CLASS__;//获取类名
      self::$instance = new $c;//如果没有创建,实例化当前类,这里实现类只实例化一次
    }
    return self::$instance;//返回类的实例
  }
  // Example类中的普通方法
  public function bark(){
    echo 'Woof!';
  }
  // 阻止用户复制对象实例
  public function __clone(){
    trigger_error('Clone is not allowed.', E_USER_ERROR);
  }
}
// 这个写法会出错,因为构造方法被声明为private
$test = new Example;
// 下面将得到Example类的单例对象
$test = Example::singleton();
$test->bark();
// 下面将得到Example类的单例对象
$test = Example::singleton();
$test->bark();
// 复制对象将导致一个E_USER_ERROR.
$test_clone = clone $test;
?>

关于__clone()方法可参考: PHP对象克隆__clone()介绍

2. 工厂模式

工厂模式在于可以根据输入参数或者应用程序配置的不同来创建一种专门用来实现化并返回其它类的实例的类。

工厂模式的例子:

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

比如这里是一个描述形状对象的工厂,它希望根据传入的参数个数不同来创建不同的形状。

<?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);
  }
}
// 根据传入的参数个数不同来创建不同的形状。
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());

使用工厂模式使得在调用方法时变得更容易,因为它只有一个类和一个方法,若没有使用工厂模式,则要在调用时决定应该调用哪个类和哪个方法;使用工厂模式还使得未来对应用程序做改变时更加容易,比如要增加一种形状的支持,只需要修改工厂类中的create()一个方法,而没有使用工厂模式,则要修改调用形状的代码块。

3. 观察者模式

观察者模式为您提供了避免组件之间紧密耦合的另一种方法。该模式非常简单:一个对象通过添加一个方法(该方法允许另一个对象,即观察者注册自己)使本身变得可观察。当可观察的对象更改时,它会将消息发送到已注册的观察者。这些观察者使用该信息执行的操作与可观察的对象无关。结果是对象可以相互对话,而不必了解原因。

一个简单的示例:当听众在收听电台时(即电台加入一个新听众),它将发送出一条提示消息,通过发送消息的日志观察者可以观察这些消息。

<?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;
      }
    }
  }
}
// 模拟一个可以被观察的类:RadioStation
class 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面向对象程序设计入门教程》、《PHP数组(Array)操作技巧大全》、《PHP基本语法入门教程》、《PHP运算与运算符用法总结》、《php字符串(string)用法总结》、《php+mysql数据库操作入门教程》及《php常见数据库操作技巧汇总》

希望本文所述对大家PHP程序设计有所帮助。

(0)

相关推荐

  • php设计模式之单例模式使用示例

    以下为单例模式代码: 复制代码 代码如下: <?phpclass EasyFramework_Easy_Mysql{    protected static $_instance = null;    private function __construct(){ }    public static function getInstance(){        if (self::$_instance === null){            self::$_instance = new s

  • php设计模式 Observer(观察者模式)

    复制代码 代码如下: <?php /** * 观察者模式 * * 定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新 * 能够便利地创建查看目标对象状态的对象,并且提供与核心对象非耦合的指定功能 * 插件系统 */ class Observerable { private $_observers = array(); public function registerObserver($observer) { $this->_observer

  • PHP最常用的2种设计模式工厂模式和单例模式介绍

    1.工厂模式 主要作用是降低耦合度. 复制代码 代码如下: abstract class Operation{ abstract public function getValue($num1,$num2); public function getAttr(){ return 1; } } class Add extends Operation{ public function getValue($num1, $num2){ return $num1+$num2; } } class Sub ex

  • php设计模式 Factory(工厂模式)

    复制代码 代码如下: <?php /** * 工厂方法模式 * * 定义一个用于创建对象的接口,让子类决定将哪一个类实例化,使用一个类的实例化延迟到其子类 */ /* class DBFactory { public static function create($type) { swtich($type) { case "Mysql": return new MysqlDB(); break; case "Postgre": return new Postg

  • php设计模式之观察者模式的应用详解

    观察者模式:定义对象间一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新. 观察者类:1.抽象主题角色:主题角色将所有对观察者对象的引用保存在一个集合中,每个主题可以任意多个观察者.抽象主题提供了增加和删除观察者对象的接口.2.抽象观察者角色:为所有的具体观察者定义一个接口,在观察的主题发生改变时更新自己3.具体主题角色:存储相关状态到具体观察者对象,当具体主题的内部状态发生改变时,给所有登记过的观察者发出通知.具体主题角色通常用一个具体子类实现.4.具体观

  • php基础设计模式大全(注册树模式、工厂模式、单列模式)

    废话不多说了,先给大家介绍注册树模式然后介绍工厂模式最后给大家介绍单列模式,本文写的很详细,一起来学习吧. php注册树模式 什么是注册树模式? 注册树模式当然也叫注册模式,注册器模式.之所以我在这里矫情一下它的名称,是因为我感觉注册树这个名称更容易让人理解.像前两篇一样,我们这篇依旧是从名字入手.注册树模式通过将对象实例注册到一棵全局的对象树上,需要的时候从对象树上采摘的模式设计方法.   这让我想起了小时候买糖葫芦,卖糖葫芦的将糖葫芦插在一个大的杆子上,人们买的时候就取下来.不同的是,注册树

  • PHP设计模式之工厂模式与单例模式

    本文实例讲述了PHP设计模式之工厂模式与单例模式实现方法.分享给大家供大家参考,具体如下: 设计模式简单说应对某类问题而设计的解决方式 工厂模式:应对需求创建相应的对象 class factory{ function __construct($name){ if(file_exists('./'.$name.'.class.php')){ return new $name; }else{ die('not exist'); } } } 单例模式:只创建一个对象的实例,不允许再创建实例,节约资源(

  • php设计模式之简单工厂模式详解

    本文以实例形式较为详细的介绍了PHP设计模式的简单工厂模式,对于进行PHP程序设计来说有很好的借鉴作用.具体如下: 一.概念 简单工厂模式 [静态工厂方法模式](Static Factory Method) 是类的创建模式 工厂模式的几种形态: 1.简单工厂模式(Simple Factory)又叫做 静态工厂方法模式(Static Factory Method) 2.工厂方法模式(Factory Method)又叫做 多态性工厂模式(Polymorphic Factory) 3.抽象工厂模式(A

  • PHP设计模式之观察者模式(Observer)详细介绍和代码实例

    [意图] 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新[GOF95] 又称为发布-订阅(Publish-Subscribe)模式.模型-视图(Model-View)模式.源-监听(Source-Listener)模式.或从属者(Dependents)模式 [观察者模式结构图] [观察者模式中主要角色] 1.抽象主题(Subject)角色:主题角色将所有对观察者对象的引用保存在一个集合中,每个主题可以有任意多个观察者. 抽象主题提供了增加和

  • php单态设计模式(单例模式)实例

    单态设计模式也叫单例模式: 1.单态设计模式含义: 单态模式的主要作用是保证在面向对象编程设计中,一个类只能有一个实例对象存在.作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统全局地提供这个实例.它不会创建实例副本,而是会向单例类内部存储的实例返回一个引用. 2.单台模式的三个关键点: ① 需要一个保存类的唯一实例的静态成员变量: ②构造函数和克隆函数必须声明为私有的,防止外部程序new类从而失去单例模式的意义: ③必须提供一个访问这个实例的公共的静态方法(通常为

随机推荐