代码之家  ›  专栏  ›  技术社区  ›  Matt

设计模式问题:封装还是继承

  •  2
  • Matt  · 技术社区  · 16 年前

    我有一个问题我已经花了很长时间了。我正在构建一个包含两个主要类的模板引擎 Template.php Tag.php Img.php 和 String.php .

    程序的工作原理如下:

    模板对象创建标记对象。每个标记对象决定要实现哪个扩展类(img、string等)。

    重点 wrap('div'), addClass('slideshow')

    每个 Img或字符串类 用于呈现特定于所需内容的代码,因此 $Img->render() <img src='blah.jpg' />

    我的问题是:

    封装

    标签.php

    function __construct($namespace, $args) {
        // Sort out namespace to determine which extension to call
        $this->extension = new $namespace($this); // Pass in Tag object so it can be used within extension
    
        return $this; // Tag object
    }
    
    function render() {
        return $this->extension->render();
    }
    

        function __construct(Tag $T) {
            $args = $T->getArgs();
            $T->addClass('img');
        }
    
        function render() {
            return '<img src="blah.jpg" />';
        }
    

    $T = new Tag("img", array(...);
    $T->render();
    

    .... 或者我应该创造更多的 继承 结构,因为“Img是一个标记”

    标签.php

    public static create($namespace, $args) {
        // Sort out namespace to determine which extension to call
        return new $namespace($args);
    
    }
    

    class Img extends Tag {
        function __construct($args) {
            // Determine namespace then call create tag
            $T = parent::__construct($namespace, $args);
        }
    
        function render() {
            return '<img src="blah.jpg" />';
        }
    }
    

    $Img = Tag::create('img', array(...));
    $Img->render();
    

    我需要的一件事是创建自定义标记的通用接口,即我可以实例化Img(…),然后实例化String(…),我确实需要使用Tag实例化每个扩展。

    同样为了澄清一下:Tag类具有所有扩展类通用的功能,Tag类中不应该有任何需要在扩展类中实现的方法。只提供helper标记函数。

    谢谢! 马特·穆勒

    2 回复  |  直到 16 年前
        1
  •  2
  •   Vivin Paliath    16 年前

    继承比将不同标记的所有功能封装在同一个标记中更有意义 Tag 班级。关注点的分离很重要,因此最好使用基于继承的方法。否则,最终在一个类中有一堆不同的特定于标记的逻辑,这很糟糕。这是一场维修噩梦!

    如果你有 Img -具体的逻辑,放在它自己的类中。您可以将所有常用方法放在 标签 班级。如果这是爪哇,我会 一个抽象类甚至是一个接口,有不同的实现( 图像 , Div

    更好的方法是 标签 接口,然后 AbstractTag 接口和扩展 抽象标签 . 但是,我不知道在PHP中这是否完全可行,但是您可以尝试做一些类似的事情。

        2
  •  1
  •   user187291    16 年前

    都不是 new Tag('img') 也没有 Tag::create('img')

     abstract class Tag { ...common methods.... }
     class ImgTag extends Tag { ...image specific methods... }
     class SpanTag extends Tag { ...image specific methods... }
    

    在模板中,只需在需要时使用新的WhateverTag

     class Template...
        function insertImage
          $tag = new ImgTag($atts);
          $tag->render();
    

    如果标签是在多个地方创建的,最好使用工厂方法,但它仍然应该属于模板

     class Template...
        function createImage
          return new ImgTag($atts);
    
        function insertOneImage
          $tag = $this->createImage
          $tag->render();
    
        function insertAnotherImage
          $tag = $this->createImage
          $tag->render();
    

    一般来说,无论如何都要避免使用静态方法。静态只是全局函数的别称,它们没有面向对象的特性。

    推荐文章