我注意到一些最近流行的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);
}
代码看起来非常易读,并且5个不同的静态类由Composer自动加载,所以乍一看这似乎是一个有吸引力的模式。我的问题是,对于那些在设计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);
}
}
现在我不得不重复自己,以便在整个地方实例化非静态类,这至少会使代码变得混乱,并且可能会使维护变得更难。
但是,另一方面,看起来每个类的静态方法也不容易扩展。假设我想使用静态API拥有多个日志;我可以尝试一些单身人士和工厂......
Logger::get('debug')->note('Handle routes for the welcome area of the site.');
Logger::get('errors')->note('Danger!');
但这似乎只是将API从方法名称转换为字符串参数(可能拼写错误等)。如果我想要两个不同的“调试”记录器怎么办?
无论是哪种方式,我倾向于静态,基于另一方,或基于另一方的实例,似乎随着模式的使用增长,我遇到了限制。
关于最佳方法的任何建议,因为我不想用重复的实例化代码填充我的应用程序,但我还希望灵活性能够根据现有的类增加更多种类?
答案 0 :(得分:0)
Laravel中的这些静态类实际上是美化的服务定位器。 "句法糖"他们称之为" Facade" (这不是一个好名字,但泰勒称之为,不要将其与http://en.wikipedia.org/wiki/Facade_pattern混淆)
Route::get('/', 'HomeController@showWelcome');
可以写成
$app['router']->get('/', 'HomeController@showWelcome');