php设计模式小结

  1、单例模式

  所谓单例模式,也就是在任何时候,应用程序中只会有这个类的一个实例存在。常见的,我们用到单例模式只让一个对象去访问数据库,从而防止打开多个数据库连接。要实现一个单例类应包括以下几点:

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

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

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

  下面是一个基本的单例模式:

  

复制代码 代码如下:

  class SingetonBasic {

  private static $instance;

  // other vars..

  private function __construct() {

  // do construct..

  }

  private function __clone() {}

  public static function getInstance() {

  if (!(self::$instance instanceof self)) {

  self::$instance = new self();

  }

  return self::$instance;

  }

  // other functions..

  }

  $a = SingetonBasic::getInstance();

  $b = SingetonBasic::getInstance();

  var_dump($a === $b);

  2、工厂模式

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

  

复制代码 代码如下:

  class FactoryBasic {

  public static function create($config) {

  }

  }

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

  

复制代码 代码如下:

  // 定义形状的公共功能:获取周长和面积。

  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、观察者模式

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

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

  

复制代码 代码如下:

  // 观察者接口

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