组合模式

来源:互联网 发布:编程社区论坛 编辑:程序博客网 时间:2024/05/17 07:47

组合模式


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

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

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

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




          具体组成:

          抽象构件角色(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和删除Removeclass 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()方法的功能,所以实现它是没有意义的。




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

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


 


          什么时候使用组合模式:

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

          组合模式的优点:

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

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

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

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

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

0 0
原创粉丝点击