Yii2设计模式——注册树模式
应用举例
在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设计模式——注册树模式的更多相关文章
- php基础设计模式 注册树模式、工厂模式、单列模式
废话不多说了,先给大家介绍注册树模式然后介绍工厂模式最后给大家介绍单列模式,本文写的很详细,一起来学习吧. php注册树模式 什么是注册树模式? 注册树模式当然也叫注册模式,注册器模式.之所以我在这里 ...
- php设计模式-注册树模式
php注册树模式 1.什么是注册树模式? 注册树模式通过将对象实例注册到全局对象树上,需要的时候将对象从全局对象树上取下来,就像小时候买糖葫芦一样,卖糖葫芦的将糖葫芦插在一个大的杆子上,人们买的时候就 ...
- php模式设计之 注册树模式
在前两篇单例模式和工厂模式后,终于迎来了最后一个基础的设计模式--注册树模式. 什么是注册树模式? 注册树模式当然也叫注册模式,注册器模式.之所以我在这里矫情一下它的名称,是因为我感觉注册树这个名称更 ...
- PHP设计模式笔记三:三种基本设计模式(工厂模式、单例模式、注册树模式) -- Rango韩老师 http://www.imooc.com/learn/236
一.工厂设计模式 index.php $db = IMooc\Factory::createDatabase(); 使用工厂类的静态方法直接创建一个dababase对象,当类名发生修改时,在工厂里修改 ...
- 2018/04/24 PHP 设计模式之注册树模式
之前学习了工厂模式和单例模式,明白了他们的意义. 但是我们在之后的使用中会发现一个问题,在新建一个实例的时候还是需要调用一个单例或者工厂,之后还是造成了代码和耦合和不好处理. 下面开始说一下: -- ...
- php设计模式之注册树模式
什么是注册树模式?[全局共享和交换对象] 注册树模式当然也叫注册模式,注册器模式.注册树模式通过将对象实例注册到一棵全局的对象树上,需要的时候从对象树上采摘的模式设计方法. 这让我想起了小时候买糖 ...
- PHP设计模式_注册树模式
通过注册树模式可以更加简单快捷的获取对象,在某个地方实例化了一个对象,可以将这个对象“保存”起来(放入可以全局使用的数组里),用的时候只需要提供 保存对象的时候 的那个标识即可,解决全局共享和交换对象 ...
- PHP模式设计之单例模式、工厂模式、注册树模式、适配器模式、观察者模式
php模式设计之单例模式 什么是单例模式? 单例模式是指在整个应用中只有一个实例对象的设计模式 为什么要用单例模式? php经常要链接数据库,如果在一个项目中频繁建立连接数据库,会造成服务器资源的很大 ...
- PHP 注册树模式
/** * 注册树模式 * 将对象注册到一个类中 * 通过该类实现全局访问操作对象 */ class Tree { private static $treeList = []; private fun ...
随机推荐
- 【STM32H7教程】第11章 STM32H7移植SEGGER的硬件异常分析
完整教程下载地址:http://forum.armfly.com/forum.php?mod=viewthread&tid=86980 第11章 STM32H7移植SEGGER的硬 ...
- numpy C语言源代码调试(三)
鉴于ddd过于简陋,希望找一个新一些的调试工具,看到有很多人推荐gdbgui,这是一个非常新的调试工具,前端使用浏览器,现在采用这一架构的软件越来越多,可以完全不必依赖庞大的gui类库,安装使用比较方 ...
- Java的自定义注解使用实例
概念 Java有五个元注解,自动继承java.lang.annotation.Annotation. 什么是元注解,可以理解为其他普通注解进行解释说明 @Target 该注解的使用范围,限定应用场景 ...
- 将包含经纬度点位信息的Excel表格数据导入到ArcMap中并输出成shapefile
将包含经纬信息的Excel表格数据,导入到ArcMap中并输出成shapefile,再进行后面的操作.使用这种方法可以将每一个包含经纬信息的数据在ArcMap中点出来. 一.准备数据 新建Excel表 ...
- ArcGIS API for JavaScript 入门教程[4] 代码的骨架
[回顾与本篇预览] 上篇简单介绍了JsAPI中的数据与视图,并告诉大家这两部分有什么用.如何有机连接在一起. 这一篇快速介绍一下前端代码的骨架.当然,假定你已经熟悉HTML5.CSS3和JavaScr ...
- 如何给自己的app添加分享到有道云笔记这样的功能
文章同步自http://javaexception.com/archives/34 如何给自己的app添加分享到有道云笔记这样的功能 问题: 在之前的一个开源笔记类项目Leanote中,有个用户反馈想 ...
- SpringBoot1
内容:
- oracle nid修改dbname
修改name的目的只是为了日后管理清晰点,不重复.我比较懒.记性又差,所以就整理记下1.检查当前nameSQL> show parameter nameNAME TYPE VALUE------ ...
- winfrom 图片裁剪 圆形头像
效果 核心代码 public Region DrawingCircle(Rectangle r) { GraphicsPath gp = new GraphicsPath(); gp.AddEllip ...
- Java 枚举类详解
1. 枚举类定义 在某些情况下,一个类的对象是有限而且固定的,比如季节类,它只有4个对象,这种实例有限而且固定的类,在Java里被称为枚举类. 2. 早期实现枚举的方式 public static f ...