设计模式学习—组合模式

1、什么是组合模式?

​ 有时候,您觉得需要在代码中使用树数据结构。树的数据结构有许多变化,但有时需要同时处理树的分支和叶子的树。组合模式允许您将对象组合到树结构中,以表示部分-整体层次结构,这意味着您可以创建由不同部分组成的对象树,但可以将其视为一个整体。组合模式允许我们以树的形式构建对象的结构,树既包含对象的组合,也包含作为节点的单个对象。

2、场景分析

复合模式可以在任何具有系统或子系统层次结构的地方实现,并且希望统一地处理单个对象和对象的组合。让我们来看一个简单的例子,其中我们使用组合模式在Java中实现html表示。html本质上是层次结构的,它从<html>标记开始,该标记是父标记或根标记,它包含其他标记,这些标记可以是父标记或子标记。Java中的复合模式可以使用组件类作为抽象类或接口来实现。在本例中,我们将使用一个抽象类,它包含复合类和叶子类中使用的所有重要方法。

import java.util.List;

public abstract class HtmlTag {
    public abstract String getTagName();

    public abstract void setStartTag(String tag);

    public abstract void setEndTag(String tag);

    public void setTagBody(String tagBody) {
        throw new UnsupportedOperationException("Current operation is not support for this object");
    }

    public void addChildTag(HtmlTag htmlTag) {
        throw new UnsupportedOperationException("Current operation is not support for this object");
    s

    public void removeChildTag(HtmlTag htmlTag) n
        throw new UnsupportedOperationException("Current operation is not support for this object");
    }

    public List<HtmlTag> getChildren() {
        throw new UnsupportedOperationException("Current operation is not support for this object");
    }

    public abstract void generateHtml();
}

​ HtmlTag类是一个组件类(Component),它定义了组合(Composite)和叶子类(Leaf)使用的所有方法。有一些方法在这两个扩展类中应该是通用的。因此,这些方法在上面的类中保持抽象,以便在子类中实现它们。

import java.util.ArrayList;
import java.util.List;

public class HtmlParentElement extends HtmlTag {
    private String tagName;
    private String startTag;
    private String endTag;
    private List<HtmlTag> childrenTag;

    public HtmlParentElement(String tagName) {
        this.tagName = tagName;
        this.startTag = "";
        this.endTag = "";
        this.childrenTag = new ArrayList<>();
    }

    @Override
    public String getTagName() {
        return tagName;
    }

    @Override
    public void setStartTag(String tag) {
        this.startTag = tag;
    }

    @Override
    public void setEndTag(String tag) {
        this.endTag = tag;
    }

    @Override
    public void addChildTag(HtmlTag htmlTag) {
        childrenTag.add(htmlTag);
    }

    @Override
    public void removeChildTag(HtmlTag htmlTag){
        childrenTag.remove(htmlTag);
    }

    @Override
    public List<HtmlTag> getChildren() {
        return childrenTag;
    }

    @Override
    public void generateHtml() {
        System.out.println(startTag);
        for (HtmlTag tag : childrenTag) {
            tag.generateHtml();
        }
        System.out.println(endTag);
    }
}

HtmlParentElement类是实现addChildTag、removeChild等方法的复合类标签,getChildren它必须由类实现,以成为结构的组合。这里的操作方法是generateHtml,它打印当前类的标记,并遍历其子类并调用它们的generateHtml方法。

public class HtmlElement extends HtmlTag {
    private String tagName;
    private String startTag;
    private String endTag;
    private String tagBody;

    public HtmlElement(String tagName) {
        this.tagName = tagName;
        this.tagBody = "";
        this.startTag = "";
        this.endTag = "";
    }

    @Override
    public String getTagName() {
        return tagName;
    }

    @Override
    public void setStartTag(String tag) {
        this.startTag = tag;
    }

    @Override
    public void setEndTag(String tag) {
        this.endTag = tag;
    }

    @Override
    public void setTagBody(String tagBody) {
        this.tagBody = tagBody;
    }

    @Override
    public void generateHtml() {
        System.out.println(startTag + "" + tagBody + "" + endTag);
    }
}

HtmlElement是leaf类,它的主要工作是实现操作方法,在本例中是generateHtml方法。它打印子元素的开始标记、可选的tagBody(如果有的话)和结束标记。让我们测试这个例子。

public class TestCompositePattern {
    public static void main(String[] args) {
        HtmlTag parentTag = new HtmlParentElement("<html>");
        parentTag.setStartTag("<html>");
        parentTag.setEndTag("</html>");
        HtmlTag p1 = new HtmlParentElement("<body>");
        p1.setStartTag("<body>");
        p1.setEndTag("</body>");
        parentTag.addChildTag(p1);
        HtmlTag child1 = new HtmlElement("<P>");
        child1.setStartTag("<P>");
        child1.setEndTag("</P>");
        child1.setTagBody("Testing html tag library");
        p1.addChildTag(child1);
        child1 = new HtmlElement("<P>");
        child1.setStartTag("<P>");
        child1.setEndTag("</P>");
        child1.setTagBody("Paragraph 2");
        p1.addChildTag(child1);
        parentTag.generateHtml();
    }
}

运行结果如下所示:

3、何时使用组合模式?

1、当您想表示对象的部分-整体层次结构时。

2、当您希望客户端能够忽略对象组合和单个对象之间的差异时。客户端将统一处理复合结构中的所有对象。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 将对象组合成树形结构 部分中体的 层次机构 组合模式使得用户对单个对象或者组合对象具有一直性 代码结合图来看。在枝...
    品味与回味阅读 340评论 0 0
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,174评论 1 32
  • 我们知道地球和一些其他行星围绕着太阳旋转,也知道在一个原子中,有许多电子围绕着原子核旋转。我曾经想象,我们的太阳系...
    yufawu阅读 807评论 0 4
  • 几分钟后,帅哥醒来,发现围着他的是几名身材粗壮的警察大汉。他慌忙摆手,误会一场。 原来,这个奇怪的家伙,就是莫问,...
    K君的人间部落阅读 980评论 8 8
  • 儿时的年味是红色的。 小时候学校一放寒假就开始盼年了,因为过年时可以穿新衣服了。妈妈在收秋之后就开始给我做千层底的...
    梅说梅写qxm阅读 666评论 0 3