组合模式

回到首页

概述

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

主要是用来处理树形结构数据,因为其应用场景的特殊性,导致了这种模式在实际的项目开发中并不那么常用。但是,一旦数据满足树形结构,应用这种模式就能发挥很大的作用,能让代码变得非常简洁。

对业务场景的一种数据结构和算法的抽象。其中,数据可以表示成树这种数据结构,业务需求可以通过在树上的递归遍历算法来实现。

结构图

 

 

代码实现

构建树并展示

抽象构件

    /// <summary>
    /// 抽象构件
    /// </summary>
    public 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);
    }

枝叶构建

    /// <summary>
    /// 枝叶构建
    /// </summary>
    public 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);
            }
        }
    }

树叶构件

    /// <summary>
    /// 树叶构件
    /// </summary>
    public 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);
        }
    }

客户端

    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();
        }
    }

运行结果

 构建公司组织架构并计算全公司薪酬

员工和部门抽象类

    //员工和部门抽象类
    public abstract class HumanResource
    {
        protected long id;
        protected double salary;
        public HumanResource(long id)
        {
            this.id = id;
        }
        public long GetId()
        {
            return id;
        }
        public abstract double CalculateSalary();
    }

枝叶构建

    //部门
    public class Department : HumanResource
    {
        List<HumanResource> subNodes = new List<HumanResource>();
        public Department(long id) : base(id)
        {
            this.id = id;
        }
        public void AddSubNode(HumanResource humanResource)
        {
            subNodes.Add(humanResource);
        }
        //计算出部门薪资
        public override double CalculateSalary()
        {
            double totalSalary = 0;
            foreach (var item in subNodes)
            {
                totalSalary += item.CalculateSalary();
            }
            return totalSalary;
        }
    }

树叶构建

    //员工
    public class Employee : HumanResource
    {
        public Employee(long id, double salary) : base(id)
        {
            this.salary = salary;
        }
        //返回员工薪资
        public override double CalculateSalary()
        {
            return salary;
        }
    }

客户端

        static void Main(string[] args)
        {
            Department root = new Department(1);
            root.AddSubNode(new Employee(11, 123.4));
            root.AddSubNode(new Employee(12, 123.5));
            root.AddSubNode(new Employee(13, 123.5));
            root.AddSubNode(new Employee(14, 123.5));
            root.AddSubNode(new Func<Department>(() =>
            {
                Department root_sub = new Department(15);
                root_sub.AddSubNode(new Employee(151, 123));
                root_sub.AddSubNode(new Employee(152, 123));
                root_sub.AddSubNode(new Employee(153, 123));
                return root_sub;
            })());
            root.AddSubNode(new Func<Department>(() =>
            {
                Department root_sub = new Department(16);
                root_sub.AddSubNode(new Employee(161, 123));
                root_sub.AddSubNode(new Employee(162, 123));
                root_sub.AddSubNode(new Employee(163, 123));
                return root_sub;
            })());
            //计算出所有值
            Console.WriteLine(root.CalculateSalary());
            Console.Read();
        }

运行结果

 

优势

高层模块调用简单。

节点自由增加。

在我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。

使用场景

当表示对象的部分-整体层次结构(树形结构)

希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。

缺陷

在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则

设计较复杂,客户端需要花更多时间理清类之间的层次关系

不容易限制容器中的构件

不容易用继承的方法来增加构件的新功能;

Demo

posted @ 2021-11-24 23:07  .NET_CJL  阅读(24)  评论(0)    收藏  举报