博客列表 >509-PHP类之模式:单例VS工厂VS注册树

509-PHP类之模式:单例VS工厂VS注册树

小威的博客
小威的博客原创
2018年05月10日 16:35:05944浏览
  •  单例模式:一个类仅允许创建一个实例

 * 例如:

 * 1.一个站点仅连接一个数据库连接对象

 * 2.一个站点仅允许存在一个配置类的实例对象


* 必须先声明一个静态私有属性:用来保存当前类的实例

* 1. 为什么必须是静态的?因为静态成员属于类,并被类所有实例所共享

* 2. 为什么必须是私有的?不允许外部直接访问,仅允许通过类方法控制方法

* 3. 为什么要有初始值null,因为类内部访问接口需要检测实例的状态,判断是否需要实例化

实例

class Config1 {}

class Config
{
	//必须先声明一个静态私有属性:用来保存当前类的实例

	private static $instance = null;

	//保存用户的自定义配置参数
	private $setting = [];

	//构造器私有化:禁止从类外部实例化
	private function __construct(){}

	//克隆方法私有化:禁止从外部克隆对象
	private function __clone(){}

        //因为用静态属性返回类实例,而只能在静态方法使用静态属性
        //所以必须创建一个静态方法来生成当前类的唯一实例
	public static function getInstance()
	{
            //检测当前类属性$instance是否已经保存了当前类的实例
            if (self::$instance == null) {
                //如果没有,则创建当前类的实例
                self::$instance = new self();
            }
            
            //如果已经有了当前类实例,就直接返回,不要重复创建类实例
            return self::$instance;
	}

	//设置配置项
	public function set($index, $value)
	{
		$this->setting[$index] = $value;
	}

	//读取配置项
	public function get($index)
	{
		return $this->setting[$index];
	}
}

$obj1 = new Config1;
$obj2 = new Config1;
var_dump($obj1,$obj2);

echo '<hr>';

//实例化Config类
$obj1 = Config::getInstance();

$obj2 = Config::getInstance();

var_dump($obj1,$obj2);

$obj1->set('host','localhost');
echo $obj1->get('host');

运行实例 »

点击 "运行实例" 按钮查看在线实例


0509.png

  • 工厂模式:用于创建多种类型的多个实例对象


实例

<?php

//声明形状类
class Shape
{
	//声明静态方法create,根据容器形状不同,创建不同图形类的实例
	public static function create($type,array $size=[])
	{
		//检测形状
		switch ($type) {
			//正方体
			case 'cube':
				return new Cube($size[0]);
				break;
			//长方体
			case 'cuboid':
			    return new Cuboid($size[0],$size[1],$size[2]);
			    break;
			//圆柱体
			case 'column':
				return new Column($size[0],$size[1],$size[2]);
			    break;
		}
	}
}

//声明正方体类
class Cube
{
	private $side; //边长
	public function __construct($side)
	{
		$this->side = $side;
	}
	//计算长方形面积: 边长  *  边长
    public function area()
    {
        return $this->side * $this->side;
    }
	//计算正方体的体积:边长*边长*边长
	public function bulk()
	{
		return $this->side * $this->side * $this->side;
	}

}

//声明长方体类
class Cuboid
{
	private $length; //长
	private $width; //宽
	private $height; //高
	public function __construct($length,$width,$height)
	{
		$this->length = $length;
		$this->width = $width;
		$this->height = $height;
	}
	//计算长方形面积: 长  * 宽
    public function area()
    {
        return $this->length * $this->width;
    }
	//计算长方体的体积:长*宽*高
	public function bulk()
	{
		return $this->length * $this->width * $this->height;
	}
}

//使用静态方法来实例化形状类,而不是用传统的new 关键字
//并根据形状类型参数的不同,来实例化不同的类,生成不同的对象
$cube = Shape::create('cube',[2]);
echo '正方形的面积是:'.$cube->area() .' 平方米'.'<br>';
echo '正方体的体积是:'.$cube->bulk() .' 立方米';

echo '<hr>';

$cuboid = Shape::create('cuboid',[2,3,4]);
echo '长方形的面积是:'.$cuboid->area() .' 平方米'.'<br>';
echo '长方体的体积是:'.$cuboid->bulk() .' 立方米';

运行实例 »

点击 "运行实例" 按钮查看在线实例


  • 注册树:其实就是创建一个对象集,也叫对象池,是用数组来进行存储的


实例

<?php

//先声明三个类,一会丢进对象树上中
class Demo1 {}
class Demo2 {}
class Demo3 {}

//声明对象注册树类
class Register
{
    //静态属性中保存着所有已经挂载到树上的对象
    public static $objs = [];
    
    //将对象挂载到树上
    public static function set($index,$obj)
    {
        self::$objs[$index] = $obj;
    }
    
    //取出对象使用
    public static function get($index)
    {
        return self::$objs[$index];
    }
    
    //已经无效的对象,及时销毁,节省资源
    public static function del($index)
    {
        unset(self::$objs[$index]);
    }
}

//先将三个类实例化后挂载到对象树上
Register::set('demo1',new Demo1);
Register::set('demo2',new Demo2);
Register::set('demo3',new Demo3);

//检测是否上树?
var_dump(Register::$objs);
echo '<hr>';
echo '<pre>'.print_r(Register::$objs,true).'</pre>';

echo '<hr>';

//用注册类的get方法查看
var_dump(Register::get('demo2'));

//删除对象池中的某个实例对象
Register::del('demo2');

//再次查看demo2对象,已经不能被查看了,因为被销毁了
var_dump(Register::get('demo2'));

运行实例 »

点击 "运行实例" 按钮查看在线实例

声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议