Design patterns 在PHP项目中,存在哪些模式来存储、访问和组织帮助对象?
在基于PHP的面向对象项目中,如何组织和管理助手对象,如数据库引擎、用户通知、错误处理等 假设我有一个大的PHP CMS。 CMS分为不同的班级。举几个例子:Design patterns 在PHP项目中,存在哪些模式来存储、访问和组织帮助对象?,design-patterns,oop,php,Design Patterns,Oop,Php,在基于PHP的面向对象项目中,如何组织和管理助手对象,如数据库引擎、用户通知、错误处理等 假设我有一个大的PHP CMS。 CMS分为不同的班级。举几个例子: 数据库对象 用户管理 用于创建/修改/删除项目的API 向最终用户显示消息的消息对象 一个上下文处理程序,可以将您带到正确的页面 显示按钮的导航栏类 日志对象 可能是自定义错误处理 等等 我正在处理一个永恒的问题,如何最好地使系统中需要这些对象的每个部分都可以访问这些对象 多年前,我的第一个建议是拥有一个$applicationglo
- 数据库对象
- 用户管理
- 用于创建/修改/删除项目的API
- 向最终用户显示消息的消息对象
- 一个上下文处理程序,可以将您带到正确的页面
- 显示按钮的导航栏类
- 日志对象
- 可能是自定义错误处理
global $application;
$application->messageHandler->addMessage("Item successfully inserted");
然后我切换到单例模式和工厂函数:
$mh =&factory("messageHandler");
$mh->addMessage("Item successfully inserted");
但我对此也不满意。单元测试和封装对我来说越来越重要,在我的理解中,globals/singleton背后的逻辑破坏了OOP的基本思想
然后,当然有可能给每个对象提供一些指向它所需的助手对象的指针,这可能是最干净、最节省资源和测试友好的方式,但我怀疑从长远来看,这种方式的可维护性
我研究过的大多数PHP框架要么使用单例模式,要么使用访问初始化对象的函数。这两种方法都很好,但正如我所说,我对两者都不满意
我想拓宽我的视野,了解这里存在哪些共同模式。我正在寻找从长期,现实世界角度讨论这一问题的示例、其他想法和参考资料
另外,我很想听听关于这个问题的专业化、利基化或普通怪异的方法
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::u constructor())定义为private,单例将只允许自身的一个实例。它只是一个“全局”变量,可用于所有“应用程序”实例。这就是为什么我认为它的使用是有效的,因为它没有忽视良好的OOP原则。当然,与世界上任何事物一样,这种“模式”也不应该被过度使用
我已经在许多PHP框架中看到了这一点,Zend框架和Yii就是其中之一。你应该使用一个框架。我不会告诉你是哪一个
附录
对于你们当中担心的人,你们仍然可以编一些线路来注入依赖关系。它可能是这样的:
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语言”
在一个应用程序中,最多只有一个应用程序类和它的每个助手的一个实例(根据上面的延迟加载)。当然,单身是不好的,但是,再说一次,除非他们不遵守现实世界。在我的例子中,他们确实如此
像“单身是坏的”这样刻板的“规则”是罪恶的根源,它们是为那些不愿为自己着想的懒人制定的
是的,我知道,从技术上讲,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();
我会避免弗拉维乌斯建议的单例方法。有许多理由避免这种做法。它违反了良好的OOP原则。谷歌测试博客上有一些关于单例和如何避免单例的好文章: 选择
- 我相信你应该:
新建你的对象($dependencyA,$dependencyB)代码>
- 您可以手动提供所需的对象(依赖项)(
)。但您也可以使用DI框架(wikipedia页面提供) 重要的是,你只传递你实际使用的东西(调用一个动作),而不是因为其他对象需要而传递给他们的东西$application=newapplication(newmessagehandler()
$object = load::singleton('classname');
//or
$object = classname::instance(); // which sets self::$instance = $this
$object = new Class();
A('Users')->getCurrentUser();