• 设计模式学习总结组合模式(Composite Method)


    问题:
    在某些情况下,
    一类具有“容器特征”的对象在充当对象的同时,又是其他对象的容器的情况,比如树状结构的对象,如果客户过多地依赖于对象容器复杂的内部实现结构,对象容器内部实现结构的变化将引起客户代码的频繁变化。如何将“客户代码与复杂的对象容器结构”解耦?让对象容器自己来实现自身的复杂结构,从而使得客户代码就像处理简单对象一样来处理复杂的对象容器?
    定义:
    组合(Composite )模式是构造型的设计模式之一,是指将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得客户对单个对象和组合对象的使用具有一致性。

    意图:
    提供一个Component角色,它定义了访问与管理部件(部分-整体)的通用接口一般包含Add(),Remove()等方法。定义一个用户存储子部件的Composite角色,他实现了Component角色提供访问与管理部件的所有方法。并维护了一个Component角色的引用列表,用于管理维护所有的子部件。这样使得基础对象可以被组合成更复杂的组合对象,而这个组合对象又可以被组合,这样不断地递归下去就形成了一个树形结构的复杂对象。组合模式就是采用树形结构来实现普遍存在的对象容器,从而将一对多的关系转化一对一的关系,使得客户代码可以一致地处理对象和对象容器,无需关心处理的是单个的对象,还是组合的对象容器。将客户程序与对象内部实现解耦,让对象容器自己来实现自身的复杂结构,解耦后,客户程序只能对象上层的接口发生关系。

    参与者:
    •抽象组件角色(Component):
    是组合中的对象声明接口,在适当的情况下,实现所有类共有接口的默认行为。声明一个接口用于访问和管理Component子部件。
    •叶组件角色(Leaf):
    在组合中表示叶节点对象没有子节点,实现抽象组件角色声明的接口。
    •子组件角色(Composite):
    在组合中表示分支节点对象,用来存储子部件,有子节点,实现抽象组件角色声明的接口如增加(add)和删除(remove)等。
    UML:


    代码说明: 

    /// <summary>
    /// 抽象组件角色(Component)
    /// </summary>
    public abstract class Component
    {
        public string Name { getset; }
        public abstract void Add(Component component);
        public abstract void Remove(Component component);
        public abstract void Show();
    }
    /// <summary>
    /// 叶组件角色(Leaf)
    /// </summary>
    public class Leaf : Component
    {
        public override void Add(Component component)
        {
            System.Console.WriteLine("我是一个叶子节点,不能添加子对象");
        }
        public override void Remove(Component component)
        {
            System.Console.WriteLine("我是一个叶子节点,没有子对象");
        }
        public override void Show()
        {
            System.Console.WriteLine("我是一个叶子节点。");
        }
    }
    /// <summary>
    /// 子组件角色(Composite)
    /// </summary>
    public class CompositeClass : Component
    {
        List<Component> list = new List<Component>();
        public override void Add(Component component)
        {
            list.Add(component);
        }
        public override void Remove(Component component)
        {
            list.Remove(component);
        }
        public override void Show()
        {
            foreach (var s in list)
            {
                System.Console.WriteLine(String.Format("我是{0}节点。",s.Name));
            }
        }
    }
    /// <summary>
    /// 客户端测试
    /// </summary>
    public void CompositeTest()
    {
        Component obj = new CompositeClass();
        obj.Name = "我是个节点";
        Component obj1 = new CompositeClass() { Name = "我还是一个节点" };
        Component obj2 = new CompositeClass() { Name = "我还是一个节点" };
        obj2.Add(new Leaf() { Name="我是一个叶子节点" });
        obj.Add(obj1);
        obj.Add(obj2);
    }

    优点:
    •客户代码与复杂的对象容器结构解耦,让对象容器自己来实现自身的复杂结构。添加或移除对象不必修改客户端代码。
    •单个对象和组合对象具有一致性接口,所以用户不必关系自己处理的是单个对象还是整个组合结构,这就简化了客户端代码。

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

    透明方式与安全方式:
    透明方式(客户端不关系,不知道使用的是Composite还是Leaf):
    在Component中声明所有用来来管理子对象的方法,包含Add(),Remove()等,这样喜欢Component接口所有的子对象都具备Add(),Remove()等,这样能达到GoF所说的“单个对象和组合对象的使用具有一致性”可是对于Leaf节点不具备Add(),Remove()等操作,这个实现是没有意义的。
    安全方式:
    在Composite中声明所有用来来管理子对象的方法,不在Leaf中定义和实现不需要的操作,这样会使Composite与Leaf不具有相同的接口,客户端调用需要做相应的判断。
    GoF比较倾向于:以不遵守单一责任原则换取透明性,让Client将组合和叶节点具有一致性。
    在实现组合模式时,有很多设计上的折衷。要根据需求平衡透明性和安全性。 

  • 相关阅读:
    字符串常量
    二维数组中的查找
    Codeforces 156B Suspects——————【逻辑判断】
    Codeforces 156 A——Message——————【思维题】
    Codeforces 639B——Bear and Forgotten Tree 3——————【构造、树】
    Codeforces 671 A——Recycling Bottles——————【思维题】
    Codeforces 550D —— Regular Bridge——————【构造】
    Codeforces 550C —— Divisibility by Eight——————【枚举 || dp】
    codeforces 638B—— Making Genome in Berland——————【类似拓扑排序】
    codeforces 675 C ——Money Transfers——————【思维题】
  • 原文地址:https://www.cnblogs.com/ejiyuan/p/2606927.html
Copyright © 2020-2023  润新知