我正在开发一个注入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
答案 0 :(得分:14)
如评论中所述,那不是相同的界面。如果您无法在所有可能的记录器实现中概括接口,请将配置差异作为实例构造函数的一部分:
class QMSLogger implements Loggable {
protected $queueName;
public function __construct($queueName) {
$this->queueName = $queueName;
}
public function log() {
...
}
}
答案 1 :(得分:13)
你问是否可能:是的,但是......
如果您实施了界面,必须尊重其合同。
interface Loggable
{
public function log();
}
此界面的合约您可以在没有任何参数的情况下致电log()
。
为了尊重这一点,您可以将参数设为可选:
class QMSLogger implements Loggable
{
public function log($queueName = null)
{
...
}
}
这是perfectly valid PHP,它尊重Liskov替代原则。当然,在对接口编码时不得使用该可选参数,否则您显然会破坏界面。只有在使用实现时(例如,在与QMSLogger
紧密耦合的代码的某些部分中),此类参数才有用。
然而,这可能不是您的问题的解决方案,因为$queueName
似乎是一个配置值,并且最好将它传递给类的构造函数(如另一个答案中所述)。
答案 2 :(得分:4)
我碰到过一个类似的案例,我想创建一个接口,以简单地确保实现该接口的所有类都具有相同的方法名称,但允许使用不同的参数实现。
/**
* Interface Loggable
* @method log
*/
interface Loggable
{
}
现在Loggable接口可以像这样使用不同的参数来实现。
class Syslogger implements Loggable
{
public function log($key, $value)
{
...
}
}
答案 3 :(得分:1)
您也可以将参数作为数组传递,这样您就可以一方面尊重合约,也可以灵活地在数组中插入任意数量的值,请查看:
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 = ...
}
祝你好运:)