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页面中文乱码分析
Oct 29 PHP
分享下页面关键字抓取www.icbase.com站点代码(带asp.net参数的)
Jan 30 PHP
php调用C代码的实现方法
Mar 11 PHP
PHP将字符分解为多个字符串的方法
Nov 22 PHP
php实现兼容2038年后Unix时间戳转换函数
Mar 18 PHP
帝国cms目录结构分享
Jul 06 PHP
crontab无法执行php的解决方法
Jan 25 PHP
PHP生成图像验证码的方法小结(2种方法)
Jul 18 PHP
PHP中类的自动加载的方法
Mar 17 PHP
thinkPHP+phpexcel实现excel报表输出功能示例
Jun 06 PHP
php检查函数必传参数是否存在的实例详解
Aug 28 PHP
PHP基于递归算法解决兔子生兔子问题
May 11 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
一段php加密解密的代码
2007/07/16 PHP
探讨Smarty中如何获取数组的长度以及smarty调用php函数的详解
2013/06/20 PHP
php中使用sftp教程
2015/03/30 PHP
php使用curl详细解析及问题汇总
2016/08/11 PHP
php简单生成一组与多组随机字符串的方法
2017/05/09 PHP
PHP观察者模式定义与用法实例分析
2019/03/22 PHP
JavaScript Perfection kill 测试及答案
2010/03/23 Javascript
js 如何实现对数据库的增删改查
2012/11/23 Javascript
探讨在JQuery和Js中,如何让ajax执行完后再继续往下执行
2013/07/09 Javascript
AngularJS内置指令
2015/02/04 Javascript
Javascript原型链的原理详解
2016/01/05 Javascript
jQuery自定义图片缩放拖拽插件imageQ实现方法(附demo源码下载)
2016/05/27 Javascript
详解Node.Js如何处理post数据
2016/09/19 Javascript
jQuery.ajax向后台传递数组问题的解决方法
2017/05/12 jQuery
React Native AsyncStorage本地存储工具类
2017/10/24 Javascript
js根据需要计算数组中重复出现某个元素的个数
2019/01/18 Javascript
微信小程序如何调用图片接口API并居中显示
2019/06/29 Javascript
Vue登录主页动态背景短视频制作
2019/09/21 Javascript
es6中new.target的作用和使用场景简单示例分析
2020/03/14 Javascript
vue 项目中当访问路由不存在的时候默认访问404页面操作
2020/08/31 Javascript
Python tkinter的grid布局及Text动态显示方法
2018/10/11 Python
python贪吃蛇游戏代码
2020/04/18 Python
Python中三元表达式的几种写法介绍
2019/03/04 Python
Python3 main函数使用sys.argv传入多个参数的实现
2019/12/25 Python
在keras下实现多个模型的融合方式
2020/05/23 Python
Python实现查找数据库最接近的数据
2020/06/08 Python
PyCharm最新激活码PyCharm2020.2.3有效
2020/11/18 Python
英国排名第一的最新设计师品牌手表独立零售商:TIC Watches
2016/09/24 全球购物
水芝澳美国官网:H2O Plus
2016/10/15 全球购物
bonprix匈牙利:女士、男士和儿童服装
2019/07/19 全球购物
英国电信商店:BT Shop
2019/12/17 全球购物
运动鞋、街头服装、手表和手袋的实时市场:StockX
2020/11/25 全球购物
七年级思品教学反思
2016/02/20 职场文书
用Python的绘图库(matplotlib)绘制小波能量谱
2021/04/17 Python
java协程框架quasar和kotlin中的协程对比分析
2022/02/24 Java/Android
python和Appium的移动端多设备自动化测试框架
2022/04/26 Python