2012-12-05 55 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中的方式。 –