应用举例

在Yii.php中:

require __DIR__ . '/BaseYii.php';

// Yii框架的帮助类,提供框架基本的功能
class Yii extends \yii\BaseYii
{
} spl_autoload_register(['Yii', 'autoload'], true, true);
Yii::$classMap = require __DIR__ . '/classes.php';
// 只在入口脚本require '../Yii.php'时创建一个Container实例
Yii::$container = new yii\di\Container();

在BaseYii中相关的部分是,

<?php

class BaseYii
{
//Yii类维持一个DI Container的单例
public static $container; //... // 在Yii框架中,除了少数情况,都是通过Yii::createObject()来创建类的实例
// 而在Yii::createObject()中始终用到一个单例Yii::$container
public static function createObject($type, array $params = [])
{
if (is_string($type)) {
return static::$container->get($type, $params);
} elseif (is_array($type) && isset($type['class'])) {
$class = $type['class'];
unset($type['class']);
return static::$container->get($class, $params, $type);
} elseif (is_callable($type, true)) {
return static::$container->invoke($type, $params);
} elseif (is_array($type)) {
throw new InvalidConfigException('Object configuration must be an array containing a "class" element.');
} throw new InvalidConfigException('Unsupported configuration type: ' . gettype($type));
} //...
}

这里使用了单例模式。

单例模式

模式定义

单例模式确保一个类只有一个实例,并提供一个全局访问点。当现实中只需要一个对象,或者为了节省系统资源,又或者是为了共享数据的时候可以使用单例模式

代码实现

我们先来看看单例模式的标准实现:

final class Singleton
{
/**
* @var Singleton
* 维持一个对自身的引用,并保证其唯一性
*/
private static $instance; // 获取实例唯一的入口
public static function getInstance(): Singleton
{
if (null === static::$instance) {
static::$instance = new static();
} return static::$instance;
} // 不允许通过new的方式产生,只能通过Singleton::getInstance()方法
private function __construct()
{
} // 也不允许clone()方法,此方法也会产生一个新的实例
private function __clone()
{
} // 也不允许反序列化,因为反序列化也会产生一个新的实例
private function __wakeup()
{
}
}

单例模式不允许产生单例的类被继承,不允许通过new方式产生,除了规定的getInstance()方法,别的实例化的途径基本被堵死。而在类的内部维持一个对自身的引用,并保证其是唯一的。

单例模式估计是所有涉及模式中最简单的了,在PHP和Yii中很少见到直接这么使用的,更多的是其变化的形式。

Yii的单例模式

Yii使用单例的场景非常多,比如请求开始创建的Application,Yii,Request,Response等对象功能都十分丰富且开销也很大,维持一个单例就可供请求的整个生命周期使用。在请求开始即创建,请求结束自行销毁,中间不销毁也不创建。这些对象使用了单例没有疑问,但是这些单例的产生、管理和使用却是有不同讲究的。

对象如何创建又如何维护,恐怕任何一个PHP框架都绕不开这个问题。Yii2采用服务定位器和依赖注入容器来提供大部分对象。在容器中使用单例好处是非常明显的。至少可以表现在节省内存和公用组件方面。

节省内存

Yii::$container 在内存中仅有一份,所有使用DI容器的场合(Application/Module等)都用到这个DI容器。 这就节省了大量的内存空间和反复构造实例的时间。

共用组件

更为重要的是,DI容器的单例化,使得Yii不同的模块共用组件成为可能。 可以想像,由于共用了DI容器,容器里面的内容也是共享的。因此,你可以在A模块中改变某个组件的状态,而B模块中可以了解到这一状态变化。 但是,如果不采用单例模式,而是每个模块(Application/Module)都维护一个自己的DI容器, 要实现这一点难度会大得多。所以,这种共享DI容器的设计是必然的、合理的。

Yii2设计模式——单例模式的更多相关文章

  1. Yii2 设计模式——单例模式

    单例模式 模式定义 单例模式确保一个类只有一个实例,并提供一个全局访问点.当现实中只需要一个对象,或者为了节省系统资源,又或者是为了共享数据的时候可以使用单例模式. 代码实现 我们先来看看单例模式的标 ...

  2. 设计模式 单例模式(Singleton) [ 转载2 ]

    设计模式 单例模式(Singleton) [ 转载2 ] @author java_my_life 单例模式的结构 单例模式的特点: 单例类只能有一个实例. 单例类必须自己创建自己的唯一实例. 单例类 ...

  3. 设计模式 单例模式(Singleton) [ 转载 ]

    设计模式 单例模式(Singleton) [ 转载 ] 转载请注明出处:http://cantellow.iteye.com/blog/838473 前言 懒汉:调用时才创建对象 饿汉:类初始化时就创 ...

  4. c#设计模式-单例模式(面试题)

    c#设计模式-单例模式 单例模式三种写法: 第一种最简单,但没有考虑线程安全,在多线程时可能会出问题, public class Singleton { private static Singleto ...

  5. java设计模式单例模式 ----懒汉式与饿汉式的区别

    常用的五种单例模式实现方式 ——主要: 1.饿汉式(线程安全,调用率高,但是,不能延迟加载.) 2.懒汉式(线程安全,调用效率不高,可以延时加载.) ——其他: 1.双重检测锁式(由于JVM底层内部模 ...

  6. Yii2设计模式——Yii2中用到哪些设计模式?

    "Yii2设计模式"包含了两个方面的内容:1.设计模式,2.Yii2框架. <设计模式>一书虽然以JAVA语言来表达设计模式的思想,但是设计模式远不限制于某一种特定的语 ...

  7. Yii2 设计模式——Yii2 中用到哪些设计模式?

    Yii 2 设计模式“包含了两个方面的内容:1. 设计模式,2. Yii 2 框架. <设计模式>一书虽然以JAVA语言来表达设计模式的思想,但是设计模式远不限制于某一种特定的语言,而是在 ...

  8. 最简单的设计模式——单例模式的演进和推荐写法(Java 版)

    前言 如下是之前总结的 C++ 版的:软件开发常用设计模式—单例模式总结(c++版),对比发现 Java 实现的单例模式和 C++ 的在线程安全上还是有些区别的. 概念不多说,没意思,我自己总结就是: ...

  9. ES6教程-字符串,函数的参数,了解函数的arguments对象,js面向对象,设计模式-单例模式,解构赋值

    前言 主要讲解了ES6对字符串的拓展,包括includes,startsWith和endsWith,另外增加了字符串模板. Start includes()是否包含 startsWith()以什么开头 ...

随机推荐

  1. Detours HOOK 库 过滤LoadLibraryExW

    Detours HOOK 库 Hook 过滤LoadLibraryExW 一丶简介 1.1 Detours库简介 Detours是微软提供的HOOK库.为我们Hook提供了方便.再也不用手撸 HOOK ...

  2. JAVA基础第五章-集合框架Map篇

    业内经常说的一句话是不要重复造轮子,但是有时候,只有自己造一个轮子了,才会深刻明白什么样的轮子适合山路,什么样的轮子适合平地! 我将会持续更新java基础知识,欢迎关注. 往期章节: JAVA基础第一 ...

  3. Spark学习之编程进阶总结(二)

    五.基于分区进行操作 基于分区对数据进行操作可以让我们避免为每个数据元素进行重复的配置工作.诸如打开数据库连接或创建随机数生成器等操作,都是我们应当尽量避免为每个元素都配置一次的工作.Spark 提供 ...

  4. [asp.net core 源码分析] 01 - Session

    1.Session文档介绍 毋庸置疑学习.Net core最好的方法之一就是学习微软.Net core的官方文档:https://docs.microsoft.com/zh-cn/aspnet/cor ...

  5. 一文带你认识Spring事务

    前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y Spring事务管理我相信大家都用得很多,但可能仅仅 ...

  6. maven 依赖中scope标签的配置范围详解

    在创建Maven项目时,需要在pom.xml 文件中添加相应的依赖,其中有一个scope标签,该标签是设置该依赖范围 (maven项目包含三种classpath{编译classpath,测试class ...

  7. Redis主从同步要深入理解?一篇文章足矣!

    前言: 今天想和大家分享有关 Redis 主从同步(也称「复制」)的内容. 我们知道,当有多台 Redis 服务器时,肯定就有一台主服务器和多台从服务器.一般来说,主服务器进行写操作,从服务器进行读操 ...

  8. 基于Vue2-Calendar改进的日历组件(含中文使用说明)

    一,前言 我是刚学Vue的菜鸟,在使用过程中需要用到日历控件,由于项目中原来是用jQuery写的,因此用了bootstarp的日历控件,但是配合Vue实在有点蛋疼,不够优雅…… 于是网上搜了好久找到了 ...

  9. 基于flexbox纯css框架的解析

    学CSS很好的一个方法大概是先用纯CSS来实现一个自己的框架,然后便可以在之后的使用中对一开始可能很粗糙的框架做细致的优化与改进,删除些冗余,添加些功能之类的. 当然,为了避免一开始写框架时候的时候手 ...

  10. 如何通过免费开源ERP Odoo建立你的团队, 销售过程和目标

    这种快速的一步一步的指南将引导您完成Odoo CRM, 帮助您轻松处理您的销售渠道, 时刻从线索到客户管理您的销售渠道. 配置 从 Odoo初始化后,生成你的数据库, 选择CRM 作为第一个app安装 ...