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 ...
随机推荐
- pods "xxx" is forbidden: SecurityContext.RunAsUser is forbidden
报错信息如下: pods "k8s-logs-cndf5" is forbidden: SecurityContext.RunAsUser is forbidden 解决方法: 需 ...
- SpringBoot框架与MyBatis集成,连接Mysql数据库
SpringBoot是一种用来简化新Spring应用初始搭建及开发过程的框架,它使用特定方式来进行配置,使得开发人员不再需要定义样板化的配置.MyBatis是一个支持普通SQL查询.存储和高级映射的持 ...
- Python进阶:全面解读高级特性之切片!
导读:切片系列文章连续写了三篇,本文是对它们做的汇总.为什么要把序列文章合并呢?在此说明一下,本文绝不是简单地将它们做了合并,主要是修正了一些严重的错误(如自定义序列切片的部分),还对行文结构与章节衔 ...
- windows下,读取快捷方式lnk所指向的路径
BOOL GetLnkFileName( OUT PWSTR pLnkName, OUT PWSTR OepnFileNameBuufer, IN DWORD OpenFileNameBufferSi ...
- iOS----------上传遇到的问题
插叙:之前电脑一直遇到VPN登录不了的问题,试了几台电脑都能正常连接,只有我的电脑不可以,VPN大佬建议我直接重装系统,索性就直接重新装了系统,结果就能连接了.昨天开始上传包的时候,发现用Applic ...
- Android注解框架实战-ButterKnife
文章大纲 Android注解框架介绍 ButterKnife实战 项目源码下载 一.框架介绍 为什么要用注解框架? 在Android开发过程中,我们经常性地需要操作组件,操作方法有findVie ...
- crontab常用
--crontab检查是否安装[oracle@rac1 ~]$ rpm -qa | grep crontabcrontabs-1.10-8启动与关闭[oracle@rac1 ~]$ /etc/init ...
- MongDB集群容灾方案步骤
MongoDB复制集优/特点支持大数据量.高扩展性.高性能.灵活数据模型.高可用性.同步机制数据复制的目的是使数据得到最大的可用性,避免单点故障引起的整站不能访问的情况的发生,Mongodb的副本集在 ...
- Redis入门教程(二)
推荐阅读: Redis入门教程(一)https://www.cnblogs.com/jichi/p/10285346.html 5. Redis 的数据结构 5.1 Redis 数据结构介绍 redi ...
- Java相关资料分享(视频+电子书籍)
正所谓“授人以鱼不如授人以渔”,你们想要的Java学习资料来啦!不管你是学生,还是已经步入职场的同行,希望你们都要珍惜眼前的学习机会,奋斗没有终点,知识永不过时. 关注底下的公众号,获取百度网盘提取码 ...