我正在开发一个正在注入Logger对象的服务,但我可以有2种不同类型的记录器,我计划有一个syslog记录器和一个队列消息系统记录器。这可能吗?
这个想法是有一个接口:
interface Loggable
{
public function log() ;
}
和实现该接口的2个类:
class Syslogger implements Loggable
{
public function log()
{
...
}
}
class QMSLogger implements Loggable
{
public function log($queueName)
{
...
}
}
我能想到的唯一方法是有一个数组作为参数,并在一个类上使用它,而不是在另一个类上使用…P
你问这是否可能:是的,它是,但是…
如果你实现一个接口,你的必须尊重它的契约。
interface Loggable
{
public function log();
}
这个接口的契约是,你可以不带任何参数调用log()
为了尊重这一点,你可以使参数可选:
class QMSLogger implements Loggable
{
public function log($queueName = null)
{
...
}
}
这是完全有效的PHP,它尊重Liskov替换原则。当然,在对接口进行编码时,不能使用这个可选参数,否则显然会破坏接口。这样的参数只有在使用实现时才有用(例如,在代码的某些部分与QMSLogger
紧密耦合)。
然而,这可能不是你的问题的解决方案,因为$queueName
似乎是一个配置值,它可能会更好地传递它在类的构造函数(如在另一个答案中解释的)。
如评论所述,这不是相同的界面。如果您不能在所有可能的日志记录器实现中泛化接口,请将配置差异作为实例构造函数的一部分:
class QMSLogger implements Loggable {
protected $queueName;
public function __construct($queueName) {
$this->queueName = $queueName;
}
public function log() {
...
}
}
我遇到过一个类似的情况,我想创建一个接口,简单地确保实现它的任何类都有一个同名的方法,但允许使用不同的参数实现。
/**
* Interface Loggable
* @method log
*/
interface Loggable
{
}
现在可以使用不同的参数实现Loggable接口,如下所示
class Syslogger implements Loggable
{
public function log($key, $value)
{
...
}
}
你也可以将参数作为数组传递,这样你一方面尊重合约,另一方面也可以灵活地在数组中插入任何数量的值,看看这个:
abstract class FeaturesAbstract
{
/**
* @param array $paramsArray
*
* @return mixed
*/
abstract public function addExecute($paramsArray);
}
要实际使用这个方法你可以像这样发送参数:
$this->abstract->addExecute(array('paramA' => $paramA, 'paramB' => $paramB));
然后在具体实现中你得到这样的参数:
/**
* @param array $paramsArray
*
* @return void
*/
public function addExecute($paramsArray)
{
$a = $paramsArray['paramA'];
$b = $paramsArray['paramB'];
$c = ...
}
祝你好运