【问题标题】:PHP Software design pattern based on static classes基于静态类的 PHP 软件设计模式
【发布时间】:2014-03-19 02:47:56
【问题描述】:

我注意到一些最近流行的 PHP 库(例如 Laravel)中的一个常见模式,其中 API 大量基于静态类和方法。此类 API 外观的典型示例:

Logger::note('Handle routes for the welcome area of the site.');
Route::match('/welcome/:id', function ($id) {
    $name = Model::from('users')->get('name')->where('id', $id);
    $body = Template::body('templates/wecome.tpl', array('name' => $name));
    HTTP::respond(200, $body);
}

代码看起来可读性很好,并且 Composer 自动加载了 5 个不同的静态类,所以乍一看,这似乎是一个很有吸引力的使用模式。我的问题是,对于那些在设计 API 方面更有经验的人来说,随着事情的扩大,这似乎是一种好方法吗?

举个例子,我可以立即看到一些笨拙的东西,例如,如果我想要保留多个日志。在非静态模式中,我可以这样做:

$debugLog = new Logger('logs/debug.log');
$errorLog = new Logger('logs/errors.log');
Route::match('/welcome/:id', function ($id) {
    $debugLog->note('Handle routes for the welcome area of the site.');
    $name = Model::from('users')->get('name')->where('id', $id);
    if (empty($name)) {
        $errorLog->warn('Name is empty!');
    }
}

但这很难在许多不同的方法和文件之间共享。

#file1.php
Route::match('/welcome/:id', function ($id) {
    $debugLog = new Logger('logs/debug.log');
    $debugLog->note('Handle routes for the welcome area of the site.');
    //etc
}
#file2.php
Route::match('/news', function ($id) {
    $debugLog = new Logger('logs/debug.log');
    $debugLog->note('Handle routes for the news area of the site.');
    if ($error) {
        $errorLog = new Logger('logs/errors.log');
        $errorLog->warn('There is some problem: '.$error);
    }
}

现在我不得不重复自己,以便在所有地方实例化非静态类,这至少会使代码混乱,并且可以说使其更难维护。

但是,另一方面,every-class-a-static 方法似乎也不容易扩展。假设我想使用静态 API 拥有多个日志;我可以尝试一些单例和工厂...

Logger::get('debug')->note('Handle routes for the welcome area of the site.');
Logger::get('errors')->note('Danger!');

但这似乎只是将 API 从方法名称转换为字符串参数(可能拼写错误等)。如果我想要两个不同的“调试”记录器怎么办?

无论我采用哪种方式,一方面基于静态,另一方面基于实例,随着模式使用的增长,我似乎遇到了限制。

鉴于我不想用重复的实例化代码填充我的应用程序,但我还希望在现有类的基础上灵活地扩展更多种类的类,关于最佳方法的任何建议?

【问题讨论】:

  • 好吧,你可能想读这个:r.je/static-methods-bad-practice.html
  • @djay +1 为那篇文章,它完美地阐明了为什么基于静态的 API 很受欢迎,但最终是个坏主意。
  • 所有基于静态类的设计模式都有一个名称:anti-patterns

标签: php oop design-patterns software-design


【解决方案1】:

Laravel 中的这些静态类实际上是美化的服务定位器。 他们称之为“Facade”的“语法糖”(不是一个好名字,但 Taylor 是这么称呼他们的,不要与 http://en.wikipedia.org/wiki/Facade_pattern 混淆)

Route::get('/', 'HomeController@showWelcome');

可以写成

$app['router']->get('/', 'HomeController@showWelcome');

阅读更多:http://taylorotwell.com/response-dont-use-facades/

【讨论】:

  • 了解 Laravel 非常有趣。还有其他例子;例如,该问题可能适用于 Flight。
  • @tereško 我们都知道,试着告诉 Laravel 的创造者,他这么称呼他们
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-07-30
  • 2010-09-14
  • 1970-01-01
  • 2015-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多