Composite(组合)模式思维导图


Composite(组合)模式思维导图

描述

定义

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

类型

对象结构型模式

UML类图

Composite模式UML类图

实现

主要角色

  • Component:抽象构件
    • 为组合中的对象声明接口。
    • 在适当的情况下,实现所有类共有接口的缺省行为。
    • 声明一个接口用于访问和管理Component的子组件。
    • (可选)在递归结构中定义一个接口,用于访问一个父部件,并在合适的情况下实现它。
  • Leaf:树叶构件
    • 在组合中表示叶节点对象,叶节点没有子节点。
    • 在组合中定义图元对象的行为。
  • Composite:树枝构件
    • 定义有子部件的那些部件的行为。
    • 存储子部件。
    • 在Component接口中实现与子部件有关的操作。
  • Client:客户端类
    • 通过Component接口操纵组合部件的对象。

安全模式 VS 透明模式

组合模式的实现根据所实现接口的区别分为两种形式:安全模式和透明模式。安全模式要求管理子组件的方法只出现在树枝构件类中,而不出现在树叶构件中。而透明模式要求所有的具体构件类,不论树枝构件还是树叶构件,均符合同一个固定的接口。

对于组合模式而言,在安全性和透明性上,会更看重透明性,毕竟组合模式的目的是:让客户端不再区分操作的是树枝对象还是树叶对象,而是以一个统一的方式来操作。而且对于安全性的实现,需要区分的是树枝对象还是树叶对象。有时候,需要将对象进行类型强行转换,这种类型转换必然是不够安全的。

因此在使用组合模式的时候,建议多采用透明式的实现方式。

透明模式代码示例

  • Component:抽象构件

      public abstract class Component {
      	public void operation();
    
      	// 安全模式中下面接口方法只位于组合构件中
      	public abstract void add(Component component);
      	public abstract void remove(Component component);
      	public abstract List<Component> getChildren();
      }
    
  • Leaf:树叶构件

      public class Leaf extends Component {
      	public void operation() {
      		System.out.println("Leaf component");
      	}
      	public void add(Component component) {
      		throw new UnsupportedOperationException("对象不支持此功能");
      	}
      	public void remove(Component component) {
      		throw new UnsupportedOperationException("对象不支持此功能");
      	}
      	// 空实现
      	public List<Component> getChildren() {
      		return new ArrayList<Component>();
      	}
      }
    
  • Composite:树枝构件

      public class Composite extends Component {
      	// 构件容器
      	private ArrayList<Component> componentArrayList = new ArrayList<Component>();
      	public void add(Component component) {
      		this.componentArrayList.add(component);
      	}
      	public void remove(Component component) {
      		this.componentArrayList.remove(component);
      	}
      	public List<Component> getChildren() {
      		return this.componentArrayList;
      	}
      	public operation() {
      		for (Component c: componentArrayList) {
      			c.operation();
      		}
      	}
      }
    
  • Client:客户端类

      public class Client {
      	public static void main(String[] args) {
      		Composite root = new Composite();
      		Leaf leaf = new Leaf();
      		leaf.operation();
      		root.add(leaf);
      		root.operation();
      	}
      }
    

适用场景

  • 需要表示对象的部分-整体层次结构。
  • 希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。

优点

  • 简化了客户端代码。Composite模式采用树形结构来实现普遍存在的对象容器,从而将“一对多”的关系转化为“一对一”的关系,使得客户代码可以一致地处理对象和对象容器,无需关心处理的是单个的对象,还是组合的对象容器。
  • 对树形结构的复杂对象容易控制。组合模式为树形结构的面向对象实现提供了一种灵活的解决方案,通过叶子对象和容器对象的递归组合,可以形成复杂的树形结构,但对树形结构的控制却非常简单。
  • 增加新构件很方便。无须对现有类库进行任何修改,符合“开闭原则”。

缺点

  • 使得设计更加复杂,客户端需要花更多时间理清类之间的层次关系。
  • 在增加新构件时很难对容器中的构件类型进行限制。在需要检测组件类型时,不能依靠编译期的类型约束来实现,必须在运行期间动态检测。

相关模式

  • 通常部件-父部件连接用于Responsibility of Chain模式。
  • Decorator模式经常与Composite模式一起使用。当装饰和组合一起使用时,它们通常有一个公共的父类。因此装饰必须支持具有add、remove和getChildren操作的Component接口。
  • Flyweight让你共享组件,但不再能引用他们的父部件。
  • (迭代器模式)Itertor可用来遍历Composite。
  • Visitor将本来应该分布在Composite和Leaf类中的操作和行为局部化。
发布了53 篇原创文章 · 获赞 8 · 访问量 1万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章