2012-12-05 24 views
1

我有一个类:记录所有操作:良好的设计模式?

class Phone 
{ 
    public function addnewnumber ($name, $number) 
    { 
    } 
} 

现在让我们想象一下,我要记录所有的操作。我不想把Logger::add();这样的东西放在addnewnumber()之内 - 也许它不可能修改那个类。那如何解决呢?

回答

1

在某些情况下,您可以使用包装对象的代理类并允许您使用__call转发函数调用。这将是这个样子:

class Proxy 
{ 
    private $_target; 
    public function __construct($target) 
    { 
     $this->_target = $target; 
    } 

    public function __call($name, $params) 
    { 
     $callable = array($this->_target, $name); 
     if (!is_callable($callable)) { 
      trigger_error('Call to undefined method '. 
          get_class($this->_target).'::'.$name, E_USER_ERROR); 
     } 

     return $this->dispatch($callable, $params); 
    } 

    protected function dispatch($callable, $params) 
    { 
     return call_user_func_array($callable, $params); 
    } 
} 

然后,您可以从这个类派生并重写dispatch执行自定义处理:

class LoggingProxy extends Proxy 
{ 
    protected function dispatch($callable, $params) 
    { 
     echo "Before calling ".get_class($callable[0]).'::'.$callable[1]."\n"; 
     $return = parent::dispatch($callable, $params); 
     echo "After calling ".get_class($callable[0]).'::'.$callable[1]."\n"; 
     return $return; 
    } 
} 

而且使用它像:

$proxy = new LoggingProxy(new Phone); 
$proxy->addnewnumber(1, 2); 

See it in action

然而,这种方法确实有一些缺点:

  • 它不与期望有特定类型的对象代码工作(你传递一个Proxy周围,而不是Phone
  • 一点也没有不允许你访问非封装类的非公开成员
1

您无法在每个类的每种方法上自动调用某些日志记录功能。如果您想将日志记录添加到手机的addnewnumber方法中,而不更改类本身,则可以将其扩展到您自己的类中。

class Phone 
{ 
    public function addnewnumber($name, $number) 
    { 
    } 
    public function somethingelse() 
    { 
    } 
} 

class MyPhone extends Phone 
{ 
    public function addnewnumber($name, $number) 
    { 
     Logger::Add(); 
     parent::addnewnumber($name, $number); 
    } 
} 

现在您的MyPhone类有所有的手机的方法,但是调用addnewnumber方法时,它记录的数量,然后调用的实际方法。

+0

那么方法的参数必须遵循扩展类,是不是那种“过劳”? –

+0

请参阅http://stackoverflow.com/questions/1603469/php-how-to-pass-child-class-construct-arguments-to-parent-construct发送动态参数。但是,是的,它总是有一些工作。但这就是它在PHP中的方式。 –