php设计模式小结


Posted in PHP onFebruary 15, 2013

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');
PHP 相关文章推荐
php中用于检测一个地理IP地址是否可用的代码
Feb 19 PHP
php 购物车完整实现代码
Jun 05 PHP
Windows7下的php环境配置教程
Feb 28 PHP
php自定义hash函数实例
May 05 PHP
php ci 获取表单中多个同名input元素值的代码
Mar 25 PHP
php处理json格式数据经典案例总结
May 19 PHP
golang与php实现计算两个经纬度之间距离的方法
Jul 22 PHP
php实现当前页面点击下载文件的简单方法
Sep 22 PHP
PHP基于GD库的图像处理方法小结
Sep 27 PHP
ThinkPHP中Widget扩展的两种写法及调用方法详解
May 04 PHP
php判断目录存在的简单方法
Sep 26 PHP
PhpStorm2020 + phpstudyV8 +XDebug的教程详解
Sep 17 PHP
php安全开发 添加随机字符串验证,防止伪造跨站请求
Feb 14 #PHP
PHP下使用CURL方式POST数据至API接口的代码
Feb 14 #PHP
PHP中通过HTTP_USER_AGENT判断是否为手机移动终端的函数代码
Feb 14 #PHP
PHP-redis中文文档介绍
Feb 07 #PHP
php中使用redis队列操作实例代码
Feb 07 #PHP
无需重新编译php加入ftp扩展的解决方法
Feb 07 #PHP
php实现utf-8和GB2312编码相互转换函数代码
Feb 07 #PHP
You might like
应用开发中涉及到的css和php笔记分享
2011/08/02 PHP
PHP中::、-&amp;gt;、self、$this几种操作符的区别介绍
2013/04/24 PHP
php简单获取目录列表的方法
2015/03/24 PHP
Android AsyncTack 异步任务实例详解
2016/11/02 PHP
Thinkphp5 微信公众号token验证不成功的原因及解决方法
2017/11/12 PHP
jQuery中文入门指南,翻译加实例,jQuery的起点教程
2007/02/09 Javascript
关于JavaScript定义类和对象的几种方式
2010/11/09 Javascript
jquery next nextAll nextUntil siblings的区别介绍
2013/10/05 Javascript
移动端js触摸事件详解
2016/09/18 Javascript
手机浏览器 后退按钮强制刷新页面方法总结
2016/10/09 Javascript
浅谈js对象属性 通过点(.) 和方括号([]) 的不同之处
2016/10/29 Javascript
Javascript基础回顾之(三) js面向对象
2017/01/31 Javascript
JS实现移动端按首字母检索城市列表附源码下载
2017/07/05 Javascript
BootStrap的双日历时间控件使用
2017/07/25 Javascript
微信小程序中post方法与get方法的封装
2017/09/26 Javascript
JavaScript设计模式之工厂模式和抽象工厂模式定义与用法分析
2018/07/26 Javascript
详解如何为你的angular app构建一个第三方库
2018/12/07 Javascript
JavaScript中遍历的十种方法总结
2020/12/15 Javascript
[00:12]DAC2018 天才少年转战三号位,他的SOLO是否仍如昔日般强大?
2018/04/06 DOTA
Python中文件I/O高效操作处理的技巧分享
2017/02/04 Python
Pycharm学习教程(3) 代码运行调试
2017/05/03 Python
python的Crypto模块实现AES加密实例代码
2018/01/22 Python
python实现字符串和字典的转换
2018/09/29 Python
详解多线程Django程序耗尽数据库连接的问题
2018/10/08 Python
Python调用adb命令实现对多台设备同时进行reboot的方法
2018/10/15 Python
pyqt5利用pyqtDesigner实现登录界面
2019/03/28 Python
python语言基本语句用法总结
2019/06/11 Python
解决Django中多条件查询的问题
2019/07/18 Python
python hash每次调用结果不同的原因
2019/11/21 Python
薇诺娜官方网上商城:专注敏感肌肤
2017/05/25 全球购物
乌克兰在线商店的价格比较:Price.ua
2019/07/26 全球购物
《兰亭集序》教学反思
2014/02/11 职场文书
元旦晚会活动总结
2014/07/09 职场文书
文明班级申报材料
2014/12/24 职场文书
论文致谢词范文
2015/05/14 职场文书
2019年感恩励志演讲稿(收藏备用)
2019/09/11 职场文书