class Application {
protected static $_singletonFoo=NULL;
public static function foo() {
if(NULL === self::$_singletonFoo) {
self::$_singletonFoo = new Foo;
}
return self::$_singletonFoo;
}
}
这就是我这样做的方式。它按需创建对象:
Application::foo()->bar();
这就是我这样做的方式,它尊重OOP原则,它比你现在的工作方式更少,并且只有在代码第一次需要它时才创建对象。
注意:我所呈现的甚至不是真正的单例模式。通过将构造函数 (Foo::__constructor()) 定义为私有,单例将只允许自身的一个实例。它只是一个可用于所有“应用程序”实例的“全局”变量。这就是为什么我认为它的使用是有效的,因为它不会忽视良好的OOP原则。当然,就像世界上任何事情一样,这种“模式”也不应该被过度使用!
我已经看到它在许多PHP框架中使用,其中包括Zend Framework和Yii。你应该使用一个框架。我不会告诉你哪一个。
补遗对于那些担心TDD的人,你仍然可以弥补一些连接来注入依赖关系。它可能看起来像这样:
class Application {
protected static $_singletonFoo=NULL;
protected static $_helperName = 'Foo';
public static function setDefaultHelperName($helperName='Foo') {
if(is_string($helperName)) {
self::$_helperName = $helperName;
}
elseif(is_object($helperName)) {
self::$_singletonFoo = $helperName;
}
else {
return FALSE;
}
return TRUE;
}
public static function foo() {
if(NULL === self::$_singletonFoo) {
self::$_singletonFoo = new self::$_helperName;
}
return self::$_singletonFoo;
}
}
有足够的改进空间。这只是一个PoC,发挥你的想象力。
为什么会这样呢?好吧,大多数时候,应用程序不会经过单元测试,它实际上会运行,希望在生产环境中运行。PHP的优势在于它的速度。PHP不是,也永远不会像Java那样成为“干净的OOP语言”。
在应用程序中,最多只有一个 Application 类,并且每个帮助程序只有一个实例(如上所述,根据延迟加载)。当然,单例是坏的,但话又说回来,前提是它们不坚持现实世界。在我的例子中,他们做到了。
像“单身是坏的”这样的刻板印象“规则”是邪恶的源泉,它们是懒惰的人不愿意为自己思考。
是的,我知道,从技术上讲,PHP宣言很糟糕。然而,它是一种成功的语言,以其黑客的方式。
补遗
一种功能样式:
function app($class) {
static $refs = array();
//> Dependency injection in case of unit test
if (is_object($class)) {
$refs[get_class($class)] = $class;
$class = get_class($class);
}
if (!isset($refs[$class]))
$refs[$class] = new $class();
return $refs[$class];
}
//> usage: app('Logger')->doWhatever();