【问题标题】:Way to change results of object's methods改变对象方法结果的方法
【发布时间】:2012-12-18 17:17:37
【问题描述】:

我试图找到一种方法来执行一些代码来更改对象方​​法的结果,而无需实际接触对象的代码。我想出的一种方法是使用装饰器:

class Decorator {
    private $object;

    public function __construct($object) {
        if (!is_object($object)) {
            throw new Exception("Not an object");
        }
        $this->object = $object;
    }

    protected function doSomething(&$val) {
        $val .= "!!";
    }

    public function __call($name, $arguments) {
        $retVal = call_user_func_array(array($this->object, $name), $arguments);
        $this->doSomething($retVal);
        return $retVal;
    }
}

class Test extends BaseTest {
    public function run() {
        return "Test->run()";
    }
}

$o = new Decorator(new Test());
$o->run();

这样它会正常工作,但它有一个缺点,这使它现在对我来说无法使用 - 它需要将所有行替换为 new Test()new Decorator(new Test()) 这正是我想要避免的 - 很多干预现有代码。也许我可以在基类中做些什么?

【问题讨论】:

  • 如果Test 扩展了一个定义了__call 的类,它的工作方式是否相同?您可以尝试这样做...

标签: php oop decorator


【解决方案1】:

一个不只是重载 PHP 中的东西。所以你想做的事是做不到的。但是你现在遇到麻烦的事实是一个很大的说明你的设计是有缺陷的。或者,如果不是您的代码设计,您必须使用的代码(我感受到您的痛苦)。

如果你不能做你想做的事,那是因为你的代码紧密耦合了。 IE。您在类中使用 new 关键字,而不是将它们 (dependency injection) 注入到需要它的类/方法中。

除了不能轻松交换类之外,由于紧密耦合,您还可以轻松地测试您的单元。

更新

为了完整性(对于未来可能的读者):如果特定类已经被命名空间并且您被允许更改命名空间,那么您可以考虑更改命名空间。然而,这并不是一个很好的做法,因为它可能会与例如自动加载器一起使用。 PSR-0 就是一个例子。但是考虑到你不能这样做,我看不出你想要什么。 附注你不应该真正使用这个“解决方案”。

更新2

似乎在某个时间出现了一些过载扩展(方式方式),但我have found 唯一关于它的事情是some bug report。不要指望它现在仍然有效。 ;-) PHP 中根本没有真正的重载。

找到了一些东西(一个不再工作的死项目,它启用了类重载):http://pecl.php.net/package/runkit

可能是另一个项目(当然也死了):http://pecl.php.net/package/apd

【讨论】:

  • 嗯,你的答案中唯一错误的是假设是我的设计和我的代码:)。否则我不能同意更多。
  • BTW 是命名空间的类,您可以更改命名空间吗?
【解决方案2】:

我不是 PHP 程序员,但我认为 AOP 是您正在寻找的。您可以尝试一些框架,例如answer中列出的一些框架。

【讨论】:

    【解决方案3】:

    来自Wikipedia article on the decorator pattern

    1. 将原始“装饰器”类子类化为“组件”类

    所以我认为您应该将要装饰的类保持为私有并仅公开已经装饰的类。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多