PHP设计模式——单例模式

PHP中的对象生存期间是从该脚本开始一直到该脚本结束为止,因此PHP的单例模式只是在一个页面中(这里可能包含很多其他页面,不是狭义的单页面)多次用到该对象时才会起作用,多次用到时不去重复的new对象(多个人做一个项目时,难免会碰到一次请求中多次实例一个对象的情况),将不会耗费不必要的资源(数据控连接操做效果很明显),还有一点就是可以保证整个脚本中都是同一个对象,这种模式是怎么实现的呢,他的实现有几个要注意的点:

1. 首先就是要将__construct()方法定义为私有方法,这样就不能通过new来得到一个新的实例了,单例模式不能在外部进行实例化,这能字自身内部进行实例化;

2. 同样要屏蔽__clone()方法,防止从类外部进行克隆

3. 然后就是定义一个用来保存实例的私有变量和获取私有变量的公有函数getInstance()

<?php
/**
 * 设计模式之单例模式
 * $_instance必须声明为静态的私有变量
 * 构造函数必须声明为私有,防止外部程序new类从而失去单例模式的意义
 * getInstance()方法必须设置为公有的,必须调用此方法以返回实例的一个引用
 * ::操作符只能访问静态变量和静态函数
 * new对象都会消耗内存
 * 使用场景:最常用的地方是数据库连接。
 * 
class Singlemodel{
    /**
     * 保存Singlemodel实例的变量
     * @var Singlemodel $_instance
     */
    private static $_instance = null;

    /**
     * 屏蔽掉通过new来实例化该对象(也可以去掉)
     * 这里来测试数据库连接
     */
    private function __construct(){
        header("Content-Type:text/html;charset=utf-8");
    }

    /**
     * 通过该方法获取实例,防止多次实例化
     */
    public static function getInstance(){
        if(!(self::$_instance instanceof self)){
            self::$_instance = new self();
        }
        return self::$_instance;
    }

    /**
     * 测试1,通过使用单例模式
     */
    public static function testOne(){
        return self::getInstance();
    }

    /**
     * 测试1,通过使用单例模式
     */
    public static function testTwo(){
        return new self();
    }

}
$obj = array();
$begin = microtime(true);
for($i=0;$i<10000;$i++){
    /*
    * 这里进行两次测试,testOne应用了单例模式,testTwo没有应用单例模式,
    * 我们分别看看他们占用的资源和耗费的时间
    */
    $obj[$i] = Singlemodel::testOne();
//    $obj[$i] = Singlemodel::testTwo();
}
echo "程序运行期间最大内存占用:".memory_get_peak_usage()."bytes\r";
echo "程序运行耗时:".floatval(microtime(true) - $begin)."s\r";

5次测试结果平均:

未使用单例模式:
程序运行期间最大内存占用:2341720bytes
程序运行耗时:0.0505061149597s

使用单例模式:
程序运行期间最大内存占用: 613272bytes
程序运行耗时:0.018285036087s

到这里,你要是自己测试过就会发现,当链接次数比较少时,差异是比较小的。其实在一次请求中达到很多次实例化也是比较少的,那么是不是说这个就没作用了呢,当然不是,你想想看,首先,这样可以尽量避免多次实例化,减小资源消耗;其次,就算是这10ms级的差距,在高并发系统中也是很有用的。我们用它好处多多

 


PHP设计模式——注册者模式

注册者模式并不是很常见,它也不是一个典型的创建模式,只是为了利用静态方法更方便的存取数据。

<?php
/**
* Registry class
*/
class Package {

  protected static $data = array();

  public static function set($key, $value) {
    self::$data[$key] = $value;
  }

  public static function get($key) {
    return isset(self::$data[$key]) ? self::$data[$key] : null;
  }

  final public static function removeObject($key) {
    if (array_key_exists($key, self::$data)) {
      unset(self::$data[$key]);
    }
  }
}


Package::set('name', 'Package name');

var_dump(Package::get('name'));
// Package name

 

 

 


PHP设计模式——简单工厂模式

  • ①抽象基类:类中定义抽象一些方法,用以在子类中实现
  • ②继承自抽象基类的子类:实现基类中的抽象方法
  • ③工厂类:用以实例化所有相对应的子类

为什么要用抽象类:

相当于制定一个规范,比如一个商场,规定必须有一个支付的方法,那我们在父类中定义一个抽象支付方法,那么继承之后就必须实现

<?php
/**
 *
 * 定义个抽象的类,让子类去继承实现它
 *
 */
abstract class Operation{
    //抽象方法不能包含函数体
    abstract public function getValue($num1,$num2);//强烈要求子类必须实现该功能函数
}

 

<?php
/**
 * 加法类
 */
class OperationAdd extends Operation {
    public function getValue($num1,$num2){
        return $num1+$num2;
    }
}

/**
 * 减法类
 */
class OperationSub extends Operation {
    public function getValue($num1,$num2){
        return $num1-$num2;
    }
}

/**
 * 乘法类
 */
class OperationMul extends Operation {
    public function getValue($num1,$num2){
        return $num1*$num2;
    }
}

/**
 * 除法类
 */
class OperationDiv extends Operation {
    public function getValue($num1,$num2){

    }
}

/**
 * 求余类(remainder)
 *
 */
class OperationRem extends Operation {
    public function getValue($num1,$num2){
 
    }
}

现在还有一个问题未解决,就是如何让程序根据用户输入的操作符实例化相应的对象呢?
解决办法:使用一个单独的类来实现实例化的过程,这个类就是工厂

<?php
/**
 * 工程类,主要用来创建对象
 * 功能:根据输入的运算符号,工厂就能实例化出合适的对象
 *
 */
class Factory{
    public static function createObj($operate){
        switch ($operate){
            case '+':
                return new OperationAdd();
                break;
            case '-':
                return new OperationSub();
                break;
            case '*':
                return new OperationMul();
                break;
            case '/':
                return new OperationDiv();
                break;
        }
    }
}
$test=Factory::createObj('+');
$result=$test->getValue(23,0);
echo $result;

其他关于关于此模式的笔记:

工厂模式:
以交通工具为例子:要求请既可以定制交通工具,又可以定制交通工具生产的过程
1>定制交通工具
1.定义一个接口,里面包含交工工具的方法(启动 运行 停止)
2.让飞机,汽车等类去实现他们
2> 定制工厂(通上类似)
1.定义一个接口,里面包含交工工具的制造方法(启动 运行 停止)
2.分别写制造飞机,汽车的工厂类去继承实现这个接口