假设你有一个唯一的对象,并且所有其他类和函数都在使用它......像$application
.
您将如何在函数中访问此对象?
-
在每个函数中使用全局变量:
global $application; $application->doStuff();
-
创建一个函数,如
application()
,将对象实例化为静态变量并返回它;然后在需要访问该对象的任何位置使用此函数:application()->doStuff();
-
创建一个单例事物,例如返回唯一实例的对象类中的静态方法,并使用此方法访问该对象:
Application::getInstance()->doStuff();
-
KingCrunch & skwee:将应用程序对象作为参数传递给需要的每个函数/类
... public function __construct(Application $app, ...){ ....
如果有其他选项,请发布它们。我想知道这些选项中哪一个是最有效/被认为是"最佳实践"的。
我会把它传递给所有需要的方法。即
function doFoo(Application $app) {
$app->doStuff();
}
全局和单例都被认为是不好的,并且过多地束缚了您的代码,这使得单元测试更加困难。当您对以下语句回答"是"时,有一条规则允许您使用单例:
我是否需要向我的应用程序引入全局状态,并且我必须具有给定对象的单个实例,并且具有多个实例将导致错误
如果您对所有 3 个部分的回答都是肯定的,那么您可以使用单例。在任何其他情况下,只需将所有实例传递给需要它们的所有方法即可。如果你有太多的上下文,请考虑使用类似上下文的东西
class Context {
public $application;
public $logger;
....
}
========
$context = new Context();
$context->application = new Application();
$context->logger = new Logger(...);
doFoo($context);
========
function doFoo(Context $context) {
$context->application->doStuff();
$context->logger->logThings();
}
(如果您需要保护数据或操作数据,或者如果您想使用惰性启动等,则可以使用 getter/setter(。
祝你好运!
单例、上帝类、单体类等都是反模式,所以我建议第四种选择:依赖注入。 您可以通过工厂在应用程序中创建application
实例(如果它没有依赖项,甚至可以new
,但这最终会使事情复杂化(。
然后,任何需要访问application
的类都可以通过构造函数将其作为成员获取。 我敢肯定,并非每个班级都需要访问application
. 记住得墨忒耳定律。
如果你需要一些通用功能,比如将一个静态字符串转换为另一个静态字符串,我建议使用 php 的全局函数(而不是,例如,一个人造静态类(。 我相信它们是为此目的而设计的。
或者只是把它交给那些对它感兴趣的人。您提出的所有建议都像全局变量一样,即使您在 3 个变体中的 2 个中不这么称呼它。
在此之前:如果你想说"这是不可能的,因为一切都需要它",那么它可能做得太多,可以太多,和/或知道太多。