组合模式的定义与特点
组合(Composite Pattern)模式的定义:有时又叫作整体-部分(Part-Whole)模式,它是一种将对象组合成树状的层次结构的模式,用来表示“整体-部分”的关系,使用户对单个对象和组合对象具有一致的访问性,属于结构型设计模式。
组合模式一般用来描述整体与部分的关系,它将对象组织到树形结构中,顶层的节点被称为根节点,根节点下面可以包含树枝节点和叶子节点,树枝节点下面又可以包含树枝节点和叶子节点,树形结构图如下。
根节点和树枝节点本质上属于同一种数据类型,可以作为容器使用;而叶子节点与树枝节点在语义上不属于用一种类型。但是在组合模式中,会把树枝节点和叶子节点看作属于同一种数据类型(用统一接口定义),让它们具备一致行为。
组合模式的主要优点
- 组合模式使得客户端代码可以一致地处理单个对象和组合对象,无须关心自己处理的是单个对象,还是组合对象,这简化了客户端代码;
更容易在组合体内加入新的对象,客户端不会因为加入了新的对象而更改源代码,满足“开闭原则”
其主要缺点
设计较复杂,客户端需要花更多时间理清类之间的层次关系;
- 不容易限制容器中的构件;
-
组合模式的结构与实现
透明方式
在该方式中,由于抽象构件声明了所有子类中的全部方法,所以客户端无须区别树叶对象和树枝对象,对客户端来说是透明的。但其缺点是:树叶构件本来没有 Add()、Remove() 及 GetChild() 方法,却要实现它们(空实现或抛异常),这样会带来一些安全性问题。
//抽象构件
public interface abstractConposite
{
public void add(abstractConposite c);
public void remove(abstractConposite c);
public abstractConposite getChild(int i);
public void operation();
}
//树枝构件
public class Root : abstractConposite
{
private List<abstractConposite> children = new List<abstractConposite>();
public void add(abstractConposite c)
{
children.Add(c);
}
public abstractConposite getChild(int i)
{
return children[i];
}
public void operation()
{
foreach (var child in children)
{
child.operation();
}
}
public void remove(abstractConposite c)
{
children.Remove(c);
}
}
//树叶构件
public class Leaf : abstractConposite
{
private string name;
public Leaf(string name)
{
this.name = name;
}
public void add(abstractConposite c)
{
//树叶是没有分支的,此处空实现
}
public abstractConposite getChild(int i)
{
return null;
}
public void operation()
{
Debug.Log("树叶 "+name+" 被访问");
}
public void remove(abstractConposite c)
{
}
}
void Start()
{
abstractConposite root0 = new Root();
abstractConposite root1 = new Root();
abstractConposite leaf1 = new Leaf("left1");
abstractConposite leaf2 = new Leaf("left2");
abstractConposite leaf3 = new Leaf("left3");
root0.add(leaf1);
root0.add(root1);
root1.add(leaf2);
root1.add(leaf3);
root0.operation();
}
//测试结果
//树叶 left1 被访问
//树叶 left2 被访问
//树叶 left3 被访问
安全方式
在该方式中,将管理子构件的方法移到树枝构件中,抽象构件和树叶构件没有对子对象的管理方法,这样就避免了上一种方式的安全性问题,但由于叶子和分支有不同的接口,客户端在调用时要知道树叶对象和树枝对象的存在,所以失去了透明性。
//抽象层只保留层次的公共行为
interface abstractConposite {
public void operation();
}
//由于把管理方法交给根构件中了,因此不能像之前用 抽象=new root 来做
void Start()
{
Root root0 = new Root();
Root root1 = new Root();
abstractConposite leaf1 = new Leaf("left1");
abstractConposite leaf2 = new Leaf("left2");
abstractConposite leaf3 = new Leaf("left3");
root0.add(leaf1);
root0.add(root1);
root1.add(leaf2);
root1.add(leaf3);
root0.operation();
}
组合模式的应用场景
前面分析了组合模式的结构与特点,下面分析它适用的以下应用场景。
在需要表示一个对象整体与部分的层次结构的场合。
- 要求对用户隐藏组合对象与单个对象的不同,用户可以用统一的接口使用组合结构中的所有对象的场合。
组合模式的扩展
对组合模式中的树叶节点和树枝节点进行抽象,也就是说树叶节点和树枝节点还有子节点,这时组合模式就扩展成复杂的组合模式了