结构类模式(三):组合(Composite)

定义

将对象组合成树形结构以表示“部分整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

有时候又叫做部分-整体模式,它使我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。

比较常见的有文件系统:文件系统由目录和文件组成。每个目录都可以装内容。目录的内容可以是文件,也可以是目录。按照这种方式,计算机的文件系统就是以递归结构来组织的。如果你想要描述这样的数据结构,那么你可以使用组合模式。

另外如果使用过Flash,会知道Flash所使用的显示列表就是一个树形结构,每个显示容器都可以包含任意多的显示对象,而显示对象又可以是显示容器。

UML

优点

  1. 使客户端调用简单,客户端可以一致的使用组合结构或其中单个对象,用户就不必关心自己处理的是单个对象还是整个组合结构,这就简化了客户端代码。
  2. 更容易在组合体内加入对象部件. 客户端不必因为加入了新的对象部件而更改代码。这一点符合开闭原则的要求,对系统的二次开发和功能扩展很有利。

缺点

  1. 组合模式不容易限制组合中的构件。

应用场景

  1. 当你发现需求中是体现部分与整体层次的结构时,以及你希望可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑使用组合模式了。
  2. 你想表示对象的部分-整体层次结构。
  3. 你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。

示例

使用组合模式构建一个树形结构。

Java

  1 import java.util.ArrayList;
  2 import java.util.List;
  3 
  4 public class Main
  5 {
  6     public static void main(String[] args)
  7     {
  8         try
  9         {
 10             //所有结点都使用基类类型定义
 11             Component root = new Composite();
 12 
 13             Component c1 = new Composite();
 14             Component c2 = new Composite();
 15 
 16             Component leaf1 = new Leaf();
 17             Component leaf2 = new Leaf();
 18             Component leaf3 = new Leaf();
 19             
 20             //添加到树形结构上
 21             root.addChild(c1);
 22             root.addChild(leaf1);
 23             
 24             c1.addChild(leaf2);
 25             c1.addChild(c2);
 26             
 27             c2.addChild(leaf3);
 28             
 29             //执行指定的一个叶子结点
 30             root.getChildAt(0).getChildAt(1).getChildAt(0).doSomething();
 31         }
 32         catch (Exception e)
 33         {
 34             e.printStackTrace();
 35         }
 36     }
 37 
 38     /**
 39      * 组合组件的基类, 所有树形结构上的结点都必须继承自该类
 40      */
 41     public static abstract class Component
 42     {
 43         public abstract void addChild(Component child) throws Exception;
 44         public abstract Component getChildAt(int index) throws Exception;
 45         public abstract void removeChild(Component child) throws Exception;
 46         public abstract void doSomething();
 47     }
 48 
 49     /**
 50      * 容器类
 51      */
 52     public static class Composite extends Component
 53     {
 54         private List<Component> _children;
 55         
 56         public Composite()
 57         {
 58             _children = new ArrayList<>();
 59         }
 60         
 61         @Override
 62         public void addChild(Component child)
 63         {
 64             _children.add(child);
 65         }
 66 
 67         @Override
 68         public Component getChildAt(int index)
 69         {
 70             return _children.get(index);
 71         }
 72 
 73         @Override
 74         public void removeChild(Component child)
 75         {
 76             _children.remove(child);
 77         }
 78 
 79         @Override
 80         public void doSomething()
 81         {
 82             System.out.println("容器对象处理了某个事务");
 83         }
 84     }
 85 
 86     /**
 87      * 叶子类
 88      */
 89     public static class Leaf extends Component
 90     {
 91         @Override
 92         public void addChild(Component child) throws Exception
 93         {
 94             throw new Exception("叶子对象不能添加子对象");
 95         }
 96 
 97         @Override
 98         public Component getChildAt(int index) throws Exception
 99         {
100             throw new Exception("叶子对象不能获取子对象");
101         }
102 
103         @Override
104         public void removeChild(Component child) throws Exception
105         {
106             throw new Exception("叶子对象不能移除子对象");
107         }
108 
109         @Override
110         public void doSomething()
111         {
112             System.out.println("叶子对象处理了某个事务");
113         }
114     }
115 }
View Code
原文地址:https://www.cnblogs.com/hammerc/p/4743787.html