注册模式和注册对象的延迟实例化

2024-05-01

让我们想象一下我们有注册表模式......

<?php

class Registry
{

private static $objects     = array();
private static $instance    = null;

public static function getInstance() {
    if (self::$instance == null) {
        self::$instance = new Registry();
    }
    return self::$instance;
}

protected function _get($key) {
    return ($this->objects[$key]) ? $this->objects[$key] : null;
}

protected function _set($key, $val) {
    $this->objects[$key] = $val;
}

public static function get($key) {
    return self::getInstance()->_get($key);
}

public static function set($key, $object) {
    return self::getInstance()->_set($key, $object);
}

}
?>

使用这个实现非常简单......

<?
Registry::set('db', $db_client);
Registry::set('redis', $redis_client);

//Using registered objects is really easy
Registry::get('db')->query("...");
Registry::get('redis')->get("...");
?>

但正如您所看到的,即使我们不需要它们,我们也会将实例添加到注册表中(是的,这一切都与性能有关)。 所以,问题是......如何修改注册表模式以便能够进行延迟实例化?

这就是我正在寻找的...

<?
class Registry
{

private static $objects     = array();
private static $instance    = null;

public static function getInstance() {
    if (self::$instance == null) {
        self::$instance = new Registry();
    }
    return self::$instance;
}

protected function _db() {
    if (!$this->objects['db']) {
        $this->objects['db'] = new DatabaseAdapter(DB_HOST, DB_NAME, DB_USER, DB_PASSWORD);
    }
    return $this->objects['db'];
}

protected function _redis() {
    if (!$this->objects['redis']) {
        $this->objects['redis'] = new Redis(REDIS_HOST, REDIS_DB, REDIS_USER, REDIS_PASSWORD);
    }
    return $this->objects['redis'];
}

public static function db() {
    return self::getInstance()->_db();
}

public static function redis() {
    return self::getInstance()->_redis();
}

}
?>

如你看到的,DatabaseAdapter() or Redis()仅在我们请求时才会创建。一切似乎都很好,但正如你所看到的,它不是一个独立的类,因为_db(), _redis()方法包含连接常量等。 如何避免呢?如何在注册表类中定义注册表方法来分离 Registy 类和其中的对象?

我真的很抱歉我的英语不好,但我希望你能明白。

谢谢。

PS:上面的所有代码都是 1 分钟编写的。之前并没有经过测试。


如果您使用全局常量,您将始终依赖于全局范围。它在哪里并不重要。另外,即使您不使用常量,您仍然依赖于注册表内的数据库类。如果你想消除这些依赖关系,你可以在要创建的类上使用工厂方法:

public function get($service)
{
    if( !this->_data[$service] ) {
        // requires PHP 5.2.3
        this->_data[$service] = call_user_func($service .'::create');
    }
    return this->_data[$service];
}

所以如果你这样做get('DB'),代码会尝试调用静态DB::create()您打算创建的类中的方法。但就像我说的,如果您使用全局常量进行配置,您只需将问题转移到另一个类中即可。

Your db类可能如下所示:

class DB
{
    protected static $_config;
    public static setConfig(array $config)
    {
        self::_config = $config;
    }
    public static create()
    {
        return new self(
            self::config['host'],
            self::config['db'],
            self::config['user'],
            self::config['pass']);
    }
}

配置可以存储在外部配置文件中,您可以在引导期间加载该文件并将其设置为数据库类,例如

DB::setConfig(parse_ini_file('/path/to/db-config.ini'));

这样做的缺点是,你必须添加create()方法遍布各处,所有类都必须能够存储自己的配置。您可以将这些职责集中到一个建造者模式 http://sourcemaking.com/design_patterns/builder。但如果你这样做了,你就成功了一半国际奥委会容器 http://en.wikipedia.org/wiki/Inversion_of_control无论如何,请查看以下资源:

  • Fabien Potencier:什么是依赖注入 http://fabien.potencier.org/article/11/what-is-dependency-injection
  • Martin Fowler:控制容器反转和依赖注入模式 http://martinfowler.com/articles/injection.html#UsingAServiceLocator
  • 设计模式——控制反转和依赖注入 http://www.codeproject.com/KB/aspnet/IOCDI.aspx
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

注册模式和注册对象的延迟实例化 的相关文章

  • 使用正则表达式提取两个短语之间的所有单词[重复]

    这个问题在这里已经有答案了 我正在尝试使用以下正则表达式提取两个短语之间的所有单词 b item W w W 0 2 1 one W w W 0 3 business b b item W w W 0 2 3 three W w W 0 3
  • 简单的 PHP 表单:电子邮件附件(代码 Golf)

    想象一下 一个用户想要在其网站上放置一个表单 该表单将允许网站访问者上传一个文件和一条简单的消息 该消息将立即通过电子邮件发送 即 该文件未存储在服务器上 或者如果该文件存储在服务器上 仅暂时 作为文件附件 并在邮件正文中添加注释 查看更多
  • post php mysql 的拆分关键字

    我有一个表存储帖子 ID 它的标签如下 Post id Tags 1 keyword1 keyword2 keyword3 我想循环遍历该表中的每一行并执行以下操作 将关键字1 关键字2 关键字3放入新表中 word id word val
  • 使用 PHP 删除文件 onclick [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我想在用户单击删除链接时删除文件 但
  • SQL:在行中保留计数或从数据库中选择计数

    示例 我有 2 张桌子 类别 Posts 在这样的类别中保留帖子编号是一个好方法吗 类别 id title posts 1 golf 50 2 soccer 90 posts id title category id 1 news 1 1
  • PHP 的 `hex2bin` 的 Node.js/JS 实现返回错误的结果。如何得到相同的结果?

    这是一段 PHP 代码 h hex2bin db6dc3f86800da4f7c19e643e8941ebb md5 md5 h echo md5 gt b885730327999e8823d113161c3538d3 这在 Node js
  • phpspreadsheet setCellValue 未写入

    我正在上传一个 Excel 文件 读取内容并使用 phpspreadsheet 写入一个新的 Excel 文件 我正在尝试创建一个 Excel 文件 我正在使用以下代码写入单元格 writesheet gt setActiveSheetIn
  • PHP CSV VLookup

    我正在寻找一个 PHP 函数 它可以读取 CSV 文件并在第 1 列上执行 vlookup 以回显第 2 列中同一行的相关值 例如 如果 CSV 包含 Name Email John j email protected cdn cgi l
  • VB 脚本 Documents.Open 抛出 424 错误

    所以我有一个vbs脚本 Function test2open sSourceFile sPDFFile Dim wApp As Word Application Dim wDoc As Word Document logStream wri
  • 使用哪个正则表达式将此字符串转换为数组?

    从 mysql 中的地理空间列我得到以下字符串值 我想将其转换为数组 最终目标是将其转换为 geoJSON POLYGON 4 885838 52 388063 4 891061 52 388381 4 890973 52 382909 该
  • 将 NULL 变量插入数据库

    我将变量设置为 NULL 我试图将其插入数据库 但由于某种原因 它们一直以 0 的形式提交 我确信我试图插入的列允许 NULL 并且默认值设置为 NULL 这是我的代码 insert NULL query mysql query INSER
  • 在 TCPDF 中设置背景颜色

    我已经手动设置了第一页的背景颜色 如下所示 pdf gt AddPage pdf gt SetFillColor 52 21 0 76 pdf gt Rect 0 0 pdf gt getPageWidth pdf gt getPageHe
  • Laravel + AngularJS Nginx 路由

    我有以下问题 我需要配置Nginx 这样在任何URL用户访问时 它都会保留uri 例如domain com some url 但仅传递给 laravel 并让 Angular 处理路由 Route get function return v
  • CodeIgniter 路由问题以访问前端和后端文件夹

    我正在使用 CodeIgniter 我在控制器和视图中有前端和后端文件夹 我尝试了服务器步骤甚至检查了几乎所有解决方案 但我仍然无法访问它我的默认控制器 路线 php route default controller frontend Us
  • Yii2 Rest - 自定义操作和 OPTIONS 方法

    我在 UsersController 类中执行以下操作 login 路由操作时遇到问题 public function actionLogin data Yii app gt getRequest gt getBodyParams mode
  • 显示产品中的类别名称和类别 ID - Laravel

    我已经找到了这个答案 但它对我不起作用 Laravel 按 id 显示类别 https stackoverflow com questions 39222584 laravel displaying categories by id 我无法
  • 依赖注入容器什么时候会变得太大,我该怎么办?

    我们都知道为什么依赖注入很棒因为它使代码耦合更少 更容易测试 并且更容易阅读 然后有些人决定使用依赖注入容器 like pimple http pimple sensiolabs org PHP 可以协助依赖倒置 http en wikip
  • 面向对象的编程和事务

    一点介绍 类包含字段和方法 这次让我跳过属性 字段代表一个state班级的 方法描述behavior班级的 在设计良好的类中 如果方法抛出异常 则不会更改类的状态 对吧 换句话说 无论发生什么 类的状态都不应该被破坏 问题 是否有一个框架
  • 带结束标记和不带结束标记的 XML(自结束标记)

    如何区别
  • 正则表达式 - 匹配单词缩写

    我正在考虑提供以下正则表达式作为答案这个问题 https stackoverflow com questions 2110010 how to find wordpresss installed on domain or server pr

随机推荐