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一些常用的正则表达式字符的一些转换
Jul 29 PHP
php正则表达匹配中文问题分析小结
Mar 25 PHP
精美漂亮的php分页类代码
Apr 02 PHP
php中的常用魔术方法总结
Aug 02 PHP
CodeIgniter基本配置详细介绍
Nov 12 PHP
PHP实现小偷程序实例
Oct 31 PHP
PHP批量获取网页中所有固定种子链接的方法
Nov 18 PHP
PHP使用DOM和simplexml读取xml文档的方法示例
Feb 08 PHP
php实现微信模拟登陆、获取用户列表及群发消息功能示例
Jun 28 PHP
PHP 多任务秒级定时器的实现方法
May 13 PHP
PHP生成二维码与识别二维码的方法详解【附源码下载】
Mar 07 PHP
php连接mysql数据库最简单的实现方法
Sep 24 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
php curl post 时出现的问题解决
2014/01/30 PHP
PHP SPL标准库之SplFixedArray使用实例
2015/05/12 PHP
PHP实现HTML页面静态化的方法
2015/11/04 PHP
ThinkPHP框架获取最后一次执行SQL语句及变量调试简单操作示例
2018/06/13 PHP
PHP5.5基于mysqli连接MySQL数据库和读取数据操作实例详解
2019/02/16 PHP
如何在centos8自定义目录安装php7.3
2019/11/28 PHP
URI、URL和URN之间的区别与联系
2006/12/20 Javascript
用javascript实现画板的代码
2007/09/05 Javascript
使用JQuery进行跨域请求
2010/01/25 Javascript
Jquery Validation插件防止重复提交表单的解决方法
2010/03/05 Javascript
Jquery index()方法 获取相应元素索引值
2012/10/12 Javascript
SeaJS入门教程系列之SeaJS介绍(一)
2014/03/03 Javascript
jQuery实现的超酷苹果风格图标滑出菜单效果代码
2015/09/16 Javascript
Nodejs中session的简单使用及通过session实现身份验证的方法
2016/02/04 NodeJs
利用Vue.js+Node.js+MongoDB实现一个博客系统(附源码)
2017/04/24 Javascript
vue+mockjs模拟数据实现前后端分离开发的实例代码
2017/08/08 Javascript
详解tween.js的使用教程
2017/09/14 Javascript
mint-ui在vue中的使用示例
2018/04/05 Javascript
JavaScript ES6中的简写语法总结与使用技巧
2018/12/30 Javascript
jQuery事件绑定和解绑、事件冒泡与阻止事件冒泡及弹出应用示例
2019/05/13 jQuery
微信小程序实现定位及到指定位置导航的示例代码
2019/08/20 Javascript
Python高效编程技巧
2013/01/07 Python
python使用adbapi实现MySQL数据库的异步存储
2019/03/19 Python
python字典一键多值实例代码分享
2019/06/14 Python
python使用装饰器作日志处理的方法
2019/07/11 Python
python自动循环定时开关机(非重启)测试
2019/08/26 Python
python super的使用方法及实例详解
2019/09/25 Python
opencv3/C++实现视频读取、视频写入
2019/12/11 Python
python3通过udp实现组播数据的发送和接收操作
2020/05/05 Python
python3 使用openpyxl将mysql数据写入xlsx的操作
2020/05/15 Python
基于python实现简单网页服务器代码实例
2020/09/14 Python
Charlotte Tilbury澳大利亚官网:英国美妆品牌
2018/10/05 全球购物
Oracle中delete,truncate和drop的区别
2016/05/05 面试题
xxx同志考察材料
2014/02/07 职场文书
Java中的继承、多态以及封装
2022/04/11 Java/Android
Spring Cloud OAuth2实现自定义token返回格式
2022/06/25 Java/Android