PHP:如何控制类的多个实例在MVC(其中多个模块加载)没有单例


PHP: How to control multiple instances of Class in MVC (where multiple modules load) without Singleton

我正在为我的项目创建一个非常基本的应用程序框架,它使用标准MVC方法并支持模块(我称之为应用程序)。有许多全局对象创建,如$URI, $ROUTER, $PROFILE,等,并访问全局库,如数组助手和日历生成器。所有这些都类似于Codeigniter或FuelPHP以及任何其他框架,但我们想要一些特定于我们需求的东西,并决定从头开始(从上面借用和修改一些库)。

我的问题是这样的。如果一个模块加载日历库,并且日历库不需要构造函数变量或依赖项(即每个新的'Calendar)将是相同的),是否有一种方法来确保只创建一个日历对象?因此,如果模块2试图创建模块1已经创建的日历对象,系统将交付相同的对象。我应该澄清一下,多个模块可以同时运行(为什么我们需要一个新的框架)。

我听说过关于单例的可怕的事情,并且对工厂没有留下深刻的印象(我可能没有正确使用工厂)。

什么是最佳实践?

谢谢!

控制反转系统如何?您可以创建一个全局IOC对象,该对象具有创建对象的指令,但它也有一个注册表,其中包含对已创建对象的引用。在模块的注册部分,对于每个您希望表现为"单例"的项目,您只需检查它是否已经被实例化。我能想到的唯一其他选择是,由于您不希望构造任何东西,因此将其设置为无法实例化的静态类并静态地访问该类(Calendar::printSomeFunction)。然而,我并不反对单例模式,不管它的价值是什么,只要它被正确使用。我只是选择更优雅的解决方案,比如#1,因为它非常灵活。但是,您无法控制开发人员是否在IOC模块之外创建类,因此您可能会考虑以某种方式保护它。

如果使用会话标志会怎样?

if(!$_SESSION['calender']){
    $calander = new Calander();
    $_SESSION['calender'] = true;
}

这个对你有用吗?

您需要的是类似于服务容器的东西。如:

$server_container->add_service("my calendar", "Calendar");

那么任何需要日历(或"my calendar"特定)的模块都可以使用:

$mymodule = new MyModule($service_container->get_service("my calendar"));
class MyModule {
    public function __construct(Calendar $calendar) { /*..*/ }
}

单例是不好的,因为它使你的代码不可测试。使用上面的代码,您可以用实现Calendar的存根替换$calendar。正确的DI会认为你也需要一个CalendarInterface,但你可能有依赖关系,不允许你做出区分。