PHP常用的三种设计模式汇总


Posted in PHP onAugust 28, 2016

本篇文章是学习PHP中常用的三种设计模式的笔记及总结,不管采用哪一门语言开发什么,几乎都会使用到设计模式,我们为什么需要设计模式呢?它的诞生对于我们开发人员来说有什么样的作用与意义呢?

相信做iOS开发的人员对设计模式也会挺熟悉吧?比如单例设计模式、工厂设计模式、观察者模式、MVC框架结构设计模式等。

接下来我们一起来学习PHP中最常用的三种设计模式:单例设计模式、工厂设计模式和观察者设计模式。

单例设计模式

所谓单例模式,即在应用程序中最多只有该类的一个实例存在,一旦创建,就会一直存在于内存中!

单例设计模式常应用于数据库类设计,采用单例模式,只连接一次数据库,防止打开多个数据库连接。

一个单例类应具备以下特点:

单例类不能直接实例化创建,而是只能由类本身实例化。因此,要获得这样的限制效果,构造函数必须标记为private,从而防止类被实例化。

需要一个私有静态成员变量来保存类实例和公开一个能访问到实例的公开静态方法。

在PHP中,为了防止他人对单例类实例克隆,通常还为其提供一个空的私有__clone()方法。

单例模式的例子:

<?php
 
/**
* Singleton of Database
*/
class Database
{
  // We need a static private variable to store a Database instance.
  privatestatic $instance;
 
  // Mark as private to prevent it from being instanced.
  privatefunction__construct()
  {
    // Do nothing.
  }
 
  privatefunction__clone() 
  {
    // Do nothing.
  }
 
  publicstatic functiongetInstance() 
  {
    if (!(self::$instanceinstanceofself)) {
      self::$instance = newself();
    }
 
    returnself::$instance;
  }
}
 
$a =Database::getInstance();
$b =Database::getInstance();
 
// true
var_dump($a === $b);

工厂设计模式

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

我们举例子,假设矩形、圆都有同样的一个方法,那么我们用基类提供的API来创建实例时,通过传参数来自动创建对应的类的实例,他们都有获取周长和面积的功能。

<?php
 
interfaceInterfaceShape 
{
 functiongetArea();
 functiongetCircumference();
}
 
/**
* 矩形
*/
class Rectangle implementsInterfaceShape
{
  private $width;
  private $height;
  
  publicfunction__construct($width, $height)
  {
    $this->width = $width;
    $this->height = $height;
  }
 
  publicfunctiongetArea() 
  {
    return $this->width* $this->height;
  }
 
  publicfunctiongetCircumference()
  {
    return 2 * $this->width + 2 * $this->height;
  }
}
 
/**
* 圆形
*/
class Circle implementsInterfaceShape
{
  private $radius;
 
  function__construct($radius)
  {
    $this->radius = $radius;
  }
 
 
  publicfunctiongetArea() 
  {
    return M_PI * pow($this->radius, 2);
  }
 
  publicfunctiongetCircumference()
  {
    return 2 * M_PI * $this->radius;
  }
}
 
/**
* 形状工厂类
*/
class FactoryShape 
{ 
  publicstatic functioncreate()
  {
    switch (func_num_args()) {
      case1:
      return newCircle(func_get_arg(0));
      case2:
      return newRectangle(func_get_arg(0), func_get_arg(1));
      default:
        # code...
        break;
    }
  } 
}
 
$rect =FactoryShape::create(5, 5);
// object(Rectangle)#1 (2) { ["width":"Rectangle":private]=> int(5) ["height":"Rectangle":private]=> int(5) }
var_dump($rect);
echo "<br>";
 
// object(Circle)#2 (1) { ["radius":"Circle":private]=> int(4) }
$circle =FactoryShape::create(4);
var_dump($circle);

观察者设计模式

观察者模式是挺常见的一种设计模式,使用得当会给程序带来非常大的便利,使用得不当,会给后来人一种难以维护的想法。

什么是观察者模式?一个对象通过提供方法允许另一个对象即观察者 注册自己)使本身变得可观察。当可观察的对象更改时,它会将消息发送到已注册的观察者。这些观察者使用该信息执行的操作与可观察的对象无关。结果是对象可以相互对话,而不必了解原因。观察者模式是一种事件系统,意味着这一模式允许某个类观察另一个类的状态,当被观察的类状态发生改变的时候,观察类可以收到通知并且做出相应的动作;观察者模式为您提供了避免组件之间紧密耦。看下面例子你就明白了!

<?php
 
/*
观察者接口
*/
interfaceInterfaceObserver
{
  functiononListen($sender, $args);
  functiongetObserverName();
}
 
// 可被观察者接口
interfaceInterfaceObservable
{
  functionaddObserver($observer);
  functionremoveObserver($observer_name);
}
 
// 观察者抽象类
abstractclass Observer implementsInterfaceObserver
{
  protected $observer_name;
 
  functiongetObserverName() 
  {
    return $this->observer_name;
  }
 
  functiononListen($sender, $args)
  {
 
  }
}
 
// 可被观察类
abstractclass Observable implementsInterfaceObservable 
{
  protected $observers = array();
 
  publicfunctionaddObserver($observer) 
  {
    if ($observerinstanceofInterfaceObserver) 
    {
      $this->observers[] = $observer;
    }
  }
 
  publicfunctionremoveObserver($observer_name) 
  {
    foreach ($this->observersas $index => $observer) 
    {
      if ($observer->getObserverName() === $observer_name) 
      {
        array_splice($this->observers, $index, 1);
        return;
      }
    }
  }
}
 
// 模拟一个可以被观察的类
class A extendsObservable 
{
  publicfunctionaddListener($listener) 
  {
    foreach ($this->observersas $observer) 
    {
      $observer->onListen($this, $listener);
    }
  }
}
 
// 模拟一个观察者类
class B extendsObserver 
{
  protected $observer_name = 'B';
 
  publicfunctiononListen($sender, $args) 
  {
    var_dump($sender);
    echo "<br>";
    var_dump($args);
    echo "<br>";
  }
}
 
// 模拟另外一个观察者类
class C extendsObserver 
{
  protected $observer_name = 'C';
 
  publicfunctiononListen($sender, $args) 
  {
    var_dump($sender);
    echo "<br>";
    var_dump($args);
    echo "<br>";
  }
}
 
$a = new A();
// 注入观察者
$a->addObserver(new B());
$a->addObserver(new C());
 
// 可以看到观察到的信息
$a->addListener('D');
 
// 移除观察者
$a->removeObserver('B');
 
// 打印的信息:
// object(A)#1 (1) { ["observers":protected]=> array(2) { [0]=> object(B)#2 (1) { ["observer_name":protected]=> string(1) "B" } [1]=> object(C)#3 (1) { ["observer_name":protected]=> string(1) "C" } } }
// string(1) "D"
// object(A)#1 (1) { ["observers":protected]=> array(2) { [0]=> object(B)#2 (1) { ["observer_name":protected]=> string(1) "B" } [1]=> object(C)#3 (1) { ["observer_name":protected]=> string(1) "C" } } }
// string(1) "D"

小结

初入PHP的世界,目前只了解这些基本的设计模式,慢慢学着去应用!如果文中有不对之处,请在评论中指出,我会在明确之后更正文章内容!

PHP 相关文章推荐
php 保留小数点
Apr 21 PHP
php 网页播放器用来播放在线视频的代码(自动判断并选择视频文件类型)
Jun 03 PHP
php中使用explode查找某个字符是否存在的方法
Jul 12 PHP
PHP mkdir()无写权限的问题解决方法
Jun 19 PHP
PHP实现的sqlite数据库连接类
Dec 12 PHP
php比较相似字符串的方法
Jun 05 PHP
PHP+AJAX实现投票功能的方法
Sep 28 PHP
php+MySQL实现登录时验证登录名和密码是否正确
May 10 PHP
PHP接收App端发送文件流的方法
Sep 23 PHP
Smarty模板常见的简单应用分析
Nov 15 PHP
PHP添加PNG图片背景透明水印操作类定义与用法示例
Mar 12 PHP
PHP解决高并发的优化方案实例
Dec 10 PHP
Apache PHP MySql安装配置图文教程
Aug 27 #PHP
php微信开发接入
Aug 27 #PHP
php微信开发自定义菜单
Aug 27 #PHP
PHP7新特性foreach 修改示例介绍
Aug 26 #PHP
简单的自定义php模板引擎
Aug 26 #PHP
PHP flush 函数使用注意事项
Aug 26 #PHP
PHP获取不了React Native Fecth参数的解决办法
Aug 26 #PHP
You might like
如何使用FireFox插件FirePHP调试PHP
2013/07/23 PHP
PHP-CGI远程代码执行漏洞分析与防范
2017/05/07 PHP
laravel 框架配置404等异常页面
2019/01/07 PHP
JS写的数字拼图小游戏代码[学习参考]
2008/10/29 Javascript
jQuery+JSON+jPlayer实现QQ空间音乐查询功能示例
2013/06/17 Javascript
js创建一个input数组并绑定click事件的方法
2014/06/12 Javascript
JavaScript获取Url里的参数
2014/12/18 Javascript
使用jquery组件qrcode生成二维码及应用指南
2015/02/22 Javascript
jQuery获取标签文本内容和html内容的方法
2015/03/27 Javascript
微信浏览器内置JavaScript对象WeixinJSBridge使用实例
2015/05/25 Javascript
CSS中position属性之fixed实现div居中
2015/12/14 Javascript
Jquery实现的简单轮播效果【附实例】
2016/04/19 Javascript
如何提高Dom访问速度
2017/01/05 Javascript
详解用node搭建简单的静态资源管理器
2017/08/09 Javascript
Vue数据监听方法watch的使用
2018/03/28 Javascript
JS中实现一个下载进度条及播放进度条的代码
2019/06/10 Javascript
在node环境下parse Smarty模板的使用示例代码
2019/11/15 Javascript
node使用request请求的方法
2019/12/20 Javascript
VueJS实现用户管理系统
2020/05/29 Javascript
微信小程序学习总结(三)条件、模板、文件引用实例分析
2020/06/04 Javascript
vantUI 获得piker选中值的自定义ID操作
2020/11/04 Javascript
详解 Python中LEGB和闭包及装饰器
2017/08/03 Python
Python实现生成随机日期字符串的方法示例
2017/12/25 Python
python 弹窗提示警告框MessageBox的实例
2019/06/18 Python
解决python 读取excel时 日期变成数字并加.0的问题
2019/10/08 Python
python 调试冷知识(小结)
2019/11/11 Python
Python操作Sqlite正确实现方法解析
2020/02/05 Python
python pyqtgraph 保存图片到本地的实例
2020/03/14 Python
CSS3教程(5):网页背景图片
2009/04/02 HTML / CSS
CSS3 中的@keyframes介绍
2014/09/02 HTML / CSS
微软瑞士官方网站:Microsoft瑞士
2018/04/20 全球购物
省文明单位申报材料
2014/05/08 职场文书
医学生求职自荐书
2014/06/12 职场文书
学校总务处领导班子民主生活会对照检查材料思想汇报
2014/09/27 职场文书
2014年团支书工作总结
2014/11/14 职场文书
导游词之平津战役纪念馆
2019/11/04 职场文书