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 相关文章推荐
mysql 搜索之简单应用
Apr 27 PHP
一步一步学习PHP(8) php 数组
Mar 05 PHP
php中获取关键词及所属来源搜索引擎名称的代码
Feb 15 PHP
php安全配置 如何配置使其更安全
Dec 16 PHP
基于PHP静态类的原罪详解
May 06 PHP
PHP实现生成透明背景的PNG缩略图函数分享
Jul 08 PHP
用 Composer构建自己的 PHP 框架之基础准备
Oct 30 PHP
[原创]PHP字符串中插入子字符串方法总结
May 06 PHP
PHP编写文件多服务器同步程序
Jul 02 PHP
使用PHP连接数据库_实现用户数据的增删改查的整体操作示例
Sep 01 PHP
PHP实现QQ、微信和支付宝三合一收款码实例代码
Feb 19 PHP
在Laravel中使用GuzzleHttp调用第三方服务的API接口代码
Oct 15 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/09/24 PHP
使用PHP实现下载CSS文件中的图片
2015/12/06 PHP
php处理单文件、多文件上传代码分享
2016/08/24 PHP
PHP二分查找算法示例【递归与非递归方法】
2016/09/29 PHP
PHP的mysqli_select_db()函数讲解
2019/01/23 PHP
根据判断浏览器类型屏幕分辨率自动调用不同CSS的代码
2007/02/22 Javascript
EasyUI中的tree用法介绍
2011/11/01 Javascript
解决jquery1.9不支持browser对象的问题
2013/11/13 Javascript
nodeType属性返回被选节点的节点类型介绍
2013/11/22 Javascript
JS显示表格内指定行html代码的方法
2015/03/31 Javascript
移动端 一个简单易懂的弹出框
2016/07/06 Javascript
webpack多页面开发实践
2017/12/18 Javascript
基于vue 动态加载图片src的解决方法
2018/02/05 Javascript
jQuery实现的页面弹幕效果【测试可用】
2018/08/17 jQuery
vue增加强缓存和版本号的实现方法
2019/05/01 Javascript
深入了解JavaScript代码覆盖
2019/06/13 Javascript
vue基础知识--axios合并请求和slot
2020/06/04 Javascript
[07:54]DOTA2 MV《我的动力鞋》 ImbaTV 出品
2014/11/21 DOTA
Python语言的12个基础知识点小结
2014/07/10 Python
Python中用于检查英文字母大写的isupper()方法
2015/05/19 Python
python2.7读取文件夹下所有文件名称及内容的方法
2018/02/24 Python
Python实现App自动签到领取积分功能
2018/09/29 Python
python清除字符串前后空格函数的方法
2018/10/21 Python
Python3.5面向对象编程图文与实例详解
2019/04/24 Python
使用Python快乐学数学Github万星神器Manim简介
2019/08/07 Python
Python的对象传递与Copy函数使用详解
2019/12/26 Python
pytorch torch.nn.AdaptiveAvgPool2d()自适应平均池化函数详解
2020/01/03 Python
ubuntu 安装pyqt5和卸载pyQt5的方法
2020/03/24 Python
Tensorflow全局设置可见GPU编号操作
2020/06/30 Python
HTML5 Video标签的属性、方法和事件汇总介绍
2015/04/24 HTML / CSS
巴西电子产品购物网站:Saldão da Informática
2018/01/09 全球购物
欧舒丹美国官网:L’Occitane美国
2018/02/23 全球购物
《争吵》教学反思
2014/02/15 职场文书
2014年医学生毕业自我鉴定
2014/03/26 职场文书
我有一个梦想演讲稿
2014/05/05 职场文书
小学生田径运动会广播稿
2014/09/11 职场文书