应用举例

在Yii.php中:

<?php

class ServiceLocator extends Component
{
//保存实例化的对象,每个对象都是单例,且有唯一string类型的ID做区分
private $_components = []; //保存设置的对象或者其定义,用于实例化
private $_definitions = []; //将对象ID作为ServiceLocator的属性,可通过$serviceLocator->{ID}直接获取
public function __get($name)
{
if ($this->has($name)) {
return $this->get($name);
} return parent::__get($name);
} //检验是否有属性$name
public function __isset($name)
{
if ($this->has($name)) {
return true;
} return parent::__isset($name);
} //检验是否有对象$id
public function has($id, $checkInstance = false)
{
return $checkInstance ? isset($this->_components[$id]) : isset($this->_definitions[$id]);
} //获取一个对象$id
public function get($id, $throwException = true)
{
//已经实例化的,直接返回
if (isset($this->_components[$id])) {
return $this->_components[$id];
} //有该对象的定义,且定义已经是一个对象,设置$_components并直接返回
if (isset($this->_definitions[$id])) {
$definition = $this->_definitions[$id];
if (is_object($definition) && !$definition instanceof Closure) {
return $this->_components[$id] = $definition;
} //有定义但不是现成对象,则交给DI Container去实例化,并且设置$_components
return $this->_components[$id] = Yii::createObject($definition);
} elseif ($throwException) {
throw new InvalidConfigException("Unknown component ID: $id");
} return null;
} //设置、存放一个对象
public function set($id, $definition)
{
unset($this->_components[$id]); if ($definition === null) {
unset($this->_definitions[$id]);
return;
} //如果$definition是对象或者类名或者callable,则注册到$_definitions中
if (is_object($definition) || is_callable($definition, true)) {
// an object, a class name, or a PHP callable
$this->_definitions[$id] = $definition;
} elseif (is_array($definition)) { //如果是带'class'的配置数组,也注册到$_definitions中
// a configuration array
if (isset($definition['class'])) {
$this->_definitions[$id] = $definition;
} else {
throw new InvalidConfigException("The configuration for the \"$id\" component must contain a \"class\" element.");
}
} else {
throw new InvalidConfigException("Unexpected configuration type for the \"$id\" component: " . gettype($definition));
}
} //清楚注册的对象
public function clear($id)
{
unset($this->_definitions[$id], $this->_components[$id]);
} }

这里用到了注册树。

注册树模式

注册树模式(Registry Pattern)又叫注册模式、注册器模式。注册树模式通过将对象实例注册到一棵全局的对象树上,需要的时候从对象树上采摘的模式设计方法。

为什么要采用注册树模式?

单例模式在整个项目中创建唯一实例的问题;工厂模式封装了对象的创建方式(工厂方法——用一个抽象方法,抽象工厂——用一簇抽象方法),使得不必总用new关键词去获取对象;创建者模式则是分步骤的创建实例的各个部分;在Yii2中则通过依赖注入容器DI去获取实例...

这些方法实际上都是解决一个问题——如何合理的产生一个对象。但对象既然已经产生出来了,怎么方便的调用这些对象呢?我们在项目内部建立的对象好像散兵游勇一样,不方便统筹管理安排啊。因而注册数模式应运而生。不管你是何种方式产生的对象,都给我“插到”注册树上。我用某个对象的时候,直接从注册树上去取一下就好了,是不是非常方便?注册时模式还为其他模式提供了一种非常好的想法。

代码实现

看看注册树模式的实现:

class Register
{
//存放对象的数组
protected static $objects; /**
* 存放一个对象
* @param $alias
* @param $object
*/
public static function set($alias,$object)
{
self::$objects[$alias] = $object;
} /**
* 获取一个对象
* @param $alias
* @return mixed
*/
public static function get($alias)
{
return self::$objects[$alias];
} /**
* 销毁一个对象
* @param $alias
*/
public static function _unset($alias)
{
unset(self::$objects[$alias]); }
}

注册树模式很类似服务定位器模式,优点是集中管理,使用方便。缺点是隐藏了对象和对象之间的依赖关系。

Yii2的注册树模式

PHP注册树模式主要用于创建对象的时候将我们的对象与相应的变量进行绑定,从这个角度上说,Yii2的Service Locator和DI Container都用到注册树模式。这二者都在内部维护一个数组(key => value),value为对象或者对象定义,在获取时通过唯一的key来获取,如果是定义再去容器里面实例化一下。

Yii2设计模式——注册树模式的更多相关文章

  1. php基础设计模式 注册树模式、工厂模式、单列模式

    废话不多说了,先给大家介绍注册树模式然后介绍工厂模式最后给大家介绍单列模式,本文写的很详细,一起来学习吧. php注册树模式 什么是注册树模式? 注册树模式当然也叫注册模式,注册器模式.之所以我在这里 ...

  2. php设计模式-注册树模式

    php注册树模式 1.什么是注册树模式? 注册树模式通过将对象实例注册到全局对象树上,需要的时候将对象从全局对象树上取下来,就像小时候买糖葫芦一样,卖糖葫芦的将糖葫芦插在一个大的杆子上,人们买的时候就 ...

  3. php模式设计之 注册树模式

    在前两篇单例模式和工厂模式后,终于迎来了最后一个基础的设计模式--注册树模式. 什么是注册树模式? 注册树模式当然也叫注册模式,注册器模式.之所以我在这里矫情一下它的名称,是因为我感觉注册树这个名称更 ...

  4. PHP设计模式笔记三:三种基本设计模式(工厂模式、单例模式、注册树模式) -- Rango韩老师 http://www.imooc.com/learn/236

    一.工厂设计模式 index.php $db = IMooc\Factory::createDatabase(); 使用工厂类的静态方法直接创建一个dababase对象,当类名发生修改时,在工厂里修改 ...

  5. 2018/04/24 PHP 设计模式之注册树模式

    之前学习了工厂模式和单例模式,明白了他们的意义. 但是我们在之后的使用中会发现一个问题,在新建一个实例的时候还是需要调用一个单例或者工厂,之后还是造成了代码和耦合和不好处理. 下面开始说一下: -- ...

  6. php设计模式之注册树模式

    什么是注册树模式?[全局共享和交换对象] 注册树模式当然也叫注册模式,注册器模式.注册树模式通过将对象实例注册到一棵全局的对象树上,需要的时候从对象树上采摘的模式设计方法.   这让我想起了小时候买糖 ...

  7. PHP设计模式_注册树模式

    通过注册树模式可以更加简单快捷的获取对象,在某个地方实例化了一个对象,可以将这个对象“保存”起来(放入可以全局使用的数组里),用的时候只需要提供 保存对象的时候 的那个标识即可,解决全局共享和交换对象 ...

  8. PHP模式设计之单例模式、工厂模式、注册树模式、适配器模式、观察者模式

    php模式设计之单例模式 什么是单例模式? 单例模式是指在整个应用中只有一个实例对象的设计模式 为什么要用单例模式? php经常要链接数据库,如果在一个项目中频繁建立连接数据库,会造成服务器资源的很大 ...

  9. PHP 注册树模式

    /** * 注册树模式 * 将对象注册到一个类中 * 通过该类实现全局访问操作对象 */ class Tree { private static $treeList = []; private fun ...

随机推荐

  1. Asp.net Core 2.2关于AutoMapper更初级的入门教程

    今天刚看到老张的哲学博客关于AutoMapper的教程,从壹开始前后端分离[ .NET Core2.0 +Vue2.0 ]框架之十三 || DTOs 对象映射使用,项目部署Windows+Linux完 ...

  2. python中的shutil模块

    目录 python中的shutil模块 目录和文件操作 归档操作 python中的shutil模块 shutil模块对文件和文件集合提供了许多高级操作,特别是提供了支持文件复制和删除的函数. 目录和文 ...

  3. asp.net core系列 54 IS4用客户端凭据保护API

    一. 概述 本篇开始进入IS4实战学习,从第一个示例开始,该示例是 “使用客户端凭据保护API”,这是使用IdentityServer保护api的最基本场景.该示例涉及到三个项目包括:Identity ...

  4. 『性能』List 和 HashSet 查找性能比较 (任何数据量的检索 从此只用 HashSet )

    结论: 总数 50000 (5万): List 检索 5W次 耗时 23秒, HashSet 检索 5W次 耗时 0.01秒. 总数 5000   (5千): List 检索 5K次 耗时 0.16秒 ...

  5. RazorPage 小测试,作下记录

    @page@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf@{}@functions{ public AppInfo item { ...

  6. 一般处理程序,将nvarchar值转换成数据类型int时失败

    系统:WIndows 10 工具:Visual Studio 2017 在写代码的过程中,我遇到了这样的一个问题.如图 vs错误提示是在SqlHelper中有错,可是怎么改都不能解决问题. 最后发现是 ...

  7. iOS----------上传遇到的问题

    插叙:之前电脑一直遇到VPN登录不了的问题,试了几台电脑都能正常连接,只有我的电脑不可以,VPN大佬建议我直接重装系统,索性就直接重新装了系统,结果就能连接了.昨天开始上传包的时候,发现用Applic ...

  8. Android新手引导库推荐

    本文同步至http://javaexception.com/archives/31 介绍一波新手引导层的库.都是star数挺高的一些库. 1.NewbieGuide(国内开发者开发) Android ...

  9. Android音视频之AudioRecord录音(一)

    在音视频开发中,录音当然是必不可少的.首先我们要学会单独的录音功能,当然这里说的录音是指用AudioRecord来录音,读取录音原始数据,读到的就是所谓的PCM数据.对于录音来说,最重要的几个参数要搞 ...

  10. git冲突时解决方法

    在多人协作中,使用git时有冲突是必然的,当git pull 下来代码的时候会出现  <<<<<<< HEAD这些东西,我也没有详细了解过这些,只是知道删除一 ...