扩展类与传递对象作为参数——性能问题


PHP Extending class vs. passing objects as parameter - performance issue

我需要建立一个类生成(和提交,验证等)web表单。我还有一个通过编写PHP代码生成原始HTML的类。

现在,在设计类来构建web表单时,我需要许多与HTML生成器相关的活动,换句话说,我需要大量的HTML生成器类完成的一些功能。我可以通过两种方式实现:

  1. 创建表单类扩展HTMl类: class WebForm extends HTML {}
  2. 我已经创建了一个HTML类的对象,(让,$html)在我的项目中的一些其他目的。我可以把它作为参数传递给WebForm类的构造函数:

    class WebForm{
        public $html;
        public function __construct($html) {
            $this->html = $html;
        }
    }
    $html = new HTML(); //  already created for some other purpose
    $webform = new WebForm($html);
    

哪个方法更快 &为什么?

这几乎可以肯定没有什么区别,除非你对HTML方法进行了数百万次调用。

如果我必须猜测(这真的只是猜测),那么我会说选项#1可能更快(而且可以忽略不计)。其基本原理是调用HTML方法所需的间接级别减少了。但确认这一理论的唯一方法是依次分析每个选项。

还要注意,在设计类时,首先应该考虑清晰度,其次才是性能(只有在确认了这是一个问题之后)。例如,你应该问问自己,让WebForm扩展HTML是否有意义;Webform 就是 HTML,这有意义吗?

用C语言来说,继承方法比聚合方法(需要额外的$this->html解引用)要快一个指针解引用操作。在PHP中应该是可比较的。

然而,一次指针解引用的代价实际上可以忽略不计您不应该将您的体系结构建立在这种纯粹的理论差异上,因为它不值得这样做。即使您已经在每秒处理数百个请求,并且需要额外的性能,这也不是正确的方法。这是首选聚合而不是继承的典型情况。

最后,考虑使Html类只具有static方法。这是完全合理的,因为它是一个助手类,所以它实际上不需要维护任何状态。如果出于某种原因您觉得它需要一些状态,请让调用者维护它并将其作为函数参数传递给Html。这不仅会改善您的设计,而且还会消除我们上面讨论的额外指针解引用。作为进一步的好处,它将完全消除实例化Html实例的开销,即使您需要在单个请求的生命周期内实例化多个WebForm对象(您考虑的两种方法都有这个缺点)。

老实说,在编写应用程序(或原型)并开始分析之前,您永远无法得到一个有根据的答案,否则您将得到基于假设的答案。

你应该考虑更多,而不仅仅是速度来构建你的应用程序。解耦、维护、可测试性和所有相关的东西。速度可能是可以忽略不计的,你选择了一个而不是另一个,但你会被困在一个维护地狱。

我建议您实现这两种方法并亲自查看。有一些工具可以帮助分析(如xdebug)。

扩展方法更快,因为您只实例化一个对象。但是,如果您只在一个页面中这样做一次,那么这是不可测量的。

对于可维护性来说,组合方法是更好的。

顺便说一句,你应该认真考虑将所有的html生成代码移到模板引擎中。只需从表单类中呈现模板,并且只在PHP中处理验证,而不是生成HTML,否则您将最终在控制器中执行与视图相关的任务。