组合模式

组合模式


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

          组合模式,又称为合成模式,或者树模式等,从名称就可以看出,组合模式和树形结构以及递归有关系。

          递归定义刻画了树的固有特性,一棵非空树是由若干棵子树构成的,而子树有可由若干棵更小的子树构成,这里的子树可以是叶子也可以是分支。

          从定义中可以得到使用组合模式的环境为:在设计中想表示对象的“部分-整体”层次结构,希望用户忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象。


组合模式_第1张图片


          具体组成:

          抽象构件角色(Component):它为组合中的对象声明接口,也可以为共有接口实现缺省行为。

          树叶构件角色(Leaf):在组合中表示叶节点对象——没有子节点,实现抽象构件角色声明的接口。

          树枝构件角色(Composite):在组合中表示分支节点对象——有子节点,实现抽象构件角色声明的接口,存储子部件。


          不管你使用的是 Leaf 类还是 Composite 类,对于客户程序来说都是一样的——客户仅仅知道Component 这个抽象类。而且在Composite 类中还持有对Component抽象类的引用,这使得Composite 中可以包含任何Component 抽象类的子类。

          组合模式的基本结构:

<span style="font-size:24px;">namespace 组合模式
{
    class Program
    {
        static void Main(string[] args)
        {
            Composite root = new Composite("root");
            root.Add(new Leaf("Leaf A"));
            root.Add(new Leaf("Leaf B"));
            Composite comp = new Composite("Composite X");
            comp .Add (new Leaf ("Leaf XA"));
            comp .Add (new Leaf ("Leaf XB"));
            root .Add (comp );
            Composite comp2=new  Composite ("Composite XY");
            comp2.Add (new Leaf ("Leaf XYA"));
            comp2.Add(new Leaf("Leaf XYB"));
            comp.Add(comp2);
            root.Add(new Leaf("Leaf C"));
            Leaf leaf=new Leaf ("Leaf D");
            root .Add (leaf );
            root .Remove (leaf );
            root .Display (1);
            Console .Read ();
        }
    }
}
//Component为组合中的对象声明接口,在适当情况下,实现所有类共有接口的默认行为
//声明一个接口用于访问和管理Component的子部件
abstract class Component
{
    protected string name;
    public Component(string name)
    {
        this.name = name;
    }
    public abstract void Add(Component c);
    public abstract void Remove(Component c);
    public abstract void Display(int depth);
}
//Leaf在组合中表示叶节点对象,叶节点没有子节点
class Leaf : Component
{
    public Leaf(string name)
        : base(name)
    { }
    public override void Add(Component c)
    {
        Console.WriteLine("Cannot add to a leaf");
    }
    public override void Remove(Component c)
    {
        Console.WriteLine("Cannot remove from a leaf");
    }
    public override void Display(int depth)
    {
        Console.WriteLine(new String('-', depth) + name);
    }
}
//Composite定义有枝节点行为,用来存储子部件
//在Component接口中实现与子部件有关的操作,比如增加Add和删除Remove
class Composite : Component
{
    private List<Component> children = new List<Component>();
    public Composite(string name)
        : base(name)
    { }
    public override void Add(Component c)
    {
        children.Add(c);
    }
    public override void Remove(Component c)
    {
        children.Remove(c);
    }
    public override void Display(int depth)
    {
        Console .WriteLine (new string ('-',depth )+name );
        foreach (Component component in children )
        {
            component .Display (depth +2);
        }
    }
}
</span>

          透明方式和安全方式:

          组合模式中必须提供对子对象的管理方法,不然无法完成对子对象的添加删除等等操作,也就失去了灵活性和扩展性。

          但是,管理方法是在 Component 中就声明还是在 Composite中声明,根据管理方法声明的位置不同,可以分为透明方式和安全方式。

          一种方式是在 Component 里面声明,所有的用来管理子类对象的方法,以达到Component接口的最大化(如下图),目的就是为了使客户看来在接口层次上树叶和分支没有区别——透明性,但树叶是不存在子类的,因此Component 声明的一些方法对于树叶来说是不适用的,这样,也就带来了一些安全性的问题。

          透明方式,就是说在Component中声明所有用来管理子对象的方法,其中包括Add、Remove等,这样实现Component接口的所有子类都具备了Add和Remove,这样做的好处就是叶节点和枝节点对于外界没有区别,它们具备完全一致的行为接口,但问题也很明显,因为Leaf类本身不具备Add()、Remove()方法的功能,所以实现它是没有意义的。


组合模式_第2张图片


          另一种方式就是只在 Composite 里面声明所有的用来管理子类对象的方法(如下图),这样就避免了上一种方式的安全性问题,但是由于叶子和分支有不同的接口,所以又失去了透明性。

          安全方式,也就是在Component接口中不去声明Add和Remove方法,那么子类的Leaf也就不需要去实现它,而是在Composite声明所有用来管理子类对象的方法,这样做就不会出现刚才提到的问题,不过由于不够透明,所以树叶和树枝类将不具有相同的接口,客户端的调用需要做相应的判断,带来了不便。


 组合模式_第3张图片


          什么时候使用组合模式:

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

          组合模式的优点:

          1、让客户可以一致的使用组合结构和单个对象。

          2、使客户端调用简单,客户端可以一致的使用组合结构或其中单个对象,用户就不必关心自己处理的是单个对象还是整个组合结构,这就简化了客户端代码。

          3、更容易在组合体内加入对象部件.客户端不必因为加入了新的对象部件而更改代码,这一点符合开闭原则的要求,对系统的二次开发和功能扩展很有利。

          组合模式的缺点:组合模式不容易限制组合中的构件。

          组合模式是一个应用非常广泛的设计模式,它本身比较简单但是很有内涵,掌握了它对我们的开发设计有很大的帮助。

你可能感兴趣的:(组合模式)