我正在开发的项目要求我有一些对象,包括事件管理器,(只读)配置管理器和插件管理器,它们在系统的任何地方都可用。
我正在使用全局变量,直到某人(具有C ++背景)友好地指出“如果你需要全局变量,你可能做错了。”
他建议使用一个传递给所有需要它的函数的状态对象
所以我做了:
$state = new State();
$state->register('eventManager' , new EventManager());
$state->register('configManager', new ConfigManager());
$state->register('cacheManager' , new CacheManager());
$state->register('pluginManager', new PluginManager());
$state->get('pluginManager')->initialize($state);
虽然我可以在更多有状态语言中看到这种方法的好处,但对于我来说,在像PHP这样的无状态语言中似乎没有意义,在页面加载完成后状态会丢失。
在PHP(大多数)无状态语言中传递状态对象是否有任何好处,它是否比其他方法(即基于全局变量的系统)具有任何优势,是否有更好的方法来处理这个?
答案 0 :(得分:2)
执行此操作的一种方法是使用单身:
class ConfigManager {
private static $instance = NULL;
public static function getInstance(){
if(self::$instance === NULL) {
self::$instance = new ConfigManager();
}
return self::$instance;
}
private function __construct(){
// Notice that this is private - only getInstance() can call this.
}
}
// When you need it:
$config = ConfigManager::getInstance();
关于如何做你要求的事情有很多不同的意见 - 我自己并不认为单身人士总是最好的方式来做到这一点。这真的取决于你的用例。
尽管如此,单身人士只是一个类的一种常见模式,其实例应该随处可见。
答案 1 :(得分:2)
您建议的注册表仍然是一个全局变量。如果你想访问一个全局变量(即使它是一个对象,尽管它是一个全局变量),你做错了。
正确的应用程序只有在全局状态发挥作用的阶段:引导它时。启动脚本的请求是全局的,与其一起发送的任何请求数据都是全局的,任何影响应用程序并存储在文件或其他适当存储中的配置都是全局的。
第一阶段应初始化一些依赖注入,将构成应用程序的所有部分放在一起。当请求的处理决定应该调用哪部分代码来响应请求时,将根据需要创建该对象图。
通常这个决定是在处理请求的框架内完成的,依赖注入也可能通过框架完成。您自己的代码只接受操作所需的值或其他所需的对象。
例如,如果您的代码需要数据库,那么您将配置数据库对象以接受数据库的URL和凭据,然后配置您的reader对象以接受该数据库对象。
依赖注入的任务是创建一个或多个数据库对象。您不必使用过时的“单例反模式”,因为它有许多缺点。
因此,在这种情况下,依赖项注入部分中存在一些对象,这些对象仅创建一次并在需要时注入。这些对象不强制仅创建一次,并且它们不存储在全局可访问的变量中。然而,某些东西必须存在于一个全局变量中,但这只是主框架对象,可能是依赖注入容器,它们永远不会作为全局变量共享到剩余的代码中 - 所以这根本就没有害处。