九、 合成(Composite)模式 --结构模式(Structural Pattern)

合成模式:有时又叫做部分-整体模式(Part-Whole)。合成模式将对象组织到树结构中,可以用来描述整体与部分的关系。合成模式可以使客户端将单纯元素与复合元素同等看待。

合成模式分为安全式和透明式

安全式合成模式类图:

 

抽象构件(Component)角色:这是一个抽象角色,它给参加组合的对象定义出公共的接口及其默认行为,可以用来管理所有的子对象。在安全式的合成模式里,构件角色并不是定义出管理子对象的方法,这一定义由树枝构件对象给出。 

树叶构件(Leaf)角色:树叶对象是没有下级子对象的对 象,定义出参加组合的原始对象的行为。  

树枝构件(Composite)角色:代表参加组合的有下级子对象的对象。树枝对象给出所有的管理子对象的方法,如 add()、remove()、getChild()等。

 

示例代码:

    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);
            root.Add(new Leaf("Leaf C"));

            Leaf Leaf1 = new Leaf("Leaf D");
            root.Add(Leaf1);
            root.Remove(Leaf1);
            root.Display(1);
            Console.ReadKey();
        }
    }

    public abstract class Component
    {
        protected string name;
        public Component(string name)
        {
            this.name = name;
        }

        public abstract void Display(int depth);
    }

    public class Composite : Component
    {
        private ArrayList children = new ArrayList();
        public Composite(string name) : base(name) { }

        public void Add(Component component)
        {
            children.Add(component);
        }

        public void Remove(Component component)
        {
            children.Remove(component);
        }

        public override void Display(int depth)
        {
            Console.WriteLine(new string('-', depth) + name);
            foreach (Component item in children)
            {
                item.Display(depth + 2);
            }
        }
    }

    class Leaf : Component
    {
        public Leaf(string name) : base(name) { }

        public override void Display(int depth)
        {
            Console.WriteLine(new String('-', depth) + name);
        }
    }
View Code

运行结果:

 

透明式合成模式类图:

透明式的合成模式要求所有的具体构件类,不论树枝构件还是树叶构件,均符合一个固定的接口。

抽象构件(Component)角色:这是一个抽象角色,它给参加组合的对象规定一个接口,规范共有的接口及默认行为。  

树叶构件(Leaf)角色:代表参加组合的树叶对象,定义 出参加组合的原始对象的行为。树叶类会给出 add()、 remove()以及 getChild()之类的用来管理子类对 对象的方法的平庸实现。  

树枝构件(Composite)角色:代表参加组合的有子对 象的对象,定义出这样的对象的行为。

示例代码:

 class CompositePartten2
    {
        public static void Main(string[] args)
        {
            Composite root = new Composite("rood");
            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);

            root.Add(new Leaf("Leaf C"));
            // Add and remove a leaf   
            Leaf l = new Leaf("Leaf D");
            root.Add(l);
            root.Remove(l);
            // Recursively display nodes   
            root.Display(1);

            Console.ReadKey();
        }
    }

    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 c);

    }

    class Composite : Component
    {
        private ArrayList children = new ArrayList();

        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 item in children)
            {
                item.Display(depth + 2);
            }
        }
    }

    class Leaf : Component
    {
        public Leaf(string name) : base(name) { }

        public override void Add(Component c)
        {
            Console.WriteLine("Connot add to leaf");
        }

        public override void Remove(Component c)
        {
            Console.WriteLine("Connot remove from a leaf");
        }

        public override void Display(int c)
        {
            Console.WriteLine(new String('-', c) + name);
        }
    }
View Code

运行结果:

使用时注意问题:

1、明显的给出父对象的引用。在子对象里面给出父对象的引用,可以很容易的遍历所有父对象。有了这个引用,可以方便的应用责任链模式。  

2、在通常的系统里,可以使用享元模式实现构件的共享,但是由于合成模式的对象经常要有对父对象的引用,因此共享不容易实现。  

3、有时候系统需要遍历一个树枝结构的子构件很多次,这 时候 可以考虑把遍历子构件的结果暂时存储在父构件里面作为缓存。  

4、关于使用什么数据类型来存储子对象的问题,在示意性的 代码中使用了 ArrayList,在实际系统中可以使用其它聚 集或数组等。  

5、客户端尽量不要直接调用树叶类中的方法,而是借助其父 类(Component)的多态性完成调用,这样可以增加代 码的复用性

posted @ 2016-02-24 16:26  mopheify  阅读(336)  评论(0编辑  收藏  举报