设计模式之------组合模式(Composite Pattern)

一、概念

①、什么是组合模式?

      组合模式又叫部分整体模式,是用于把一组相似的对象当做一个单一的对象。组合模式依据树型结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构性模式,它创建了对象组的树形结构。

②、主要解决的问题?

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

③、如何解决?

     树枝和叶子实现统一接口,数值内容组合该接口。

④、何时使用?

    1、想要表示对象的部分-整体层次结构(树型结构)。2、希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。

⑤、优点和缺点?

 优点:高层模块调用简单,节点自由添加。

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

二、图

①、结构图

②、拓展图

三、代码

①、代码类图

 

转换为树图

组合模式:客户可以一致地使用组合结构(root3)和单个对象(comp1),其实就是树干上加叶子的问题,用户不用关心到底是处理一个叶节点还是处理一个组合组件。基本对象可以被组合成更复杂的组合对象,而这个组合对象又可以被组合,这样不断地递归下去。

②、代码

 class Program
    { //客户端调用
        static void Main(string[] args)
         {
            ConCreteCompany root = new ConCreteCompany("北京总公司"); //找到一颗树根种树:通过枝节点实例化root(北京总公司)对象
            root.Add(new HRDepartment("总公司人力资源部"));           //主树干上长出了一片叶子:用HRDepartment类实例化一个对象,并将其加到树主干上面
            root.Add(new FinanceDepartment("总公司财务部"));          //主树干上又长出了一片叶子:用FinanceDepartment类实例化一个对象,并将其加到树的主干上面

            ConCreteCompany comp = new ConCreteCompany("上海华东分公司"); //主树干上长出了一个枝干:实例化一个comp对象(上海华东分公司)
            comp.Add(new HRDepartment("华东分公司人力资源部"));       //在枝干上长出了一片叶子(实例化叶节点)
            comp.Add(new FinanceDepartment("华东分公司财务部"));      //在枝干上又长出了一片叶子(华东分公司财务部)
            root.Add(comp);                                           //主树干上长出了带叶子的枝干:将comp对象添加到主树干上

            ConCreteCompany comp1 = new ConCreteCompany("南京办事处");
            comp1.Add(new HRDepartment("南京办事处人力资源部"));
            comp1.Add(new FinanceDepartment("南京办事处财务部"));
            comp.Add(comp1);

            ConCreteCompany comp2 = new ConCreteCompany("杭州办事处");
            comp2.Add(new HRDepartment("杭州办事处人力资源部"));
            comp2.Add(new FinanceDepartment("杭州办事处财务部"));
            comp.Add(comp2);

            Console.WriteLine("\n结构图:");                           //在控制台内写入内容
            root.Display(1);                                          //调取主树干的显示方法:传递过去的整数参数为1:表示“-”符号显示一个
            Console.WriteLine("\n职责:");    
            root.LineOfDuty();                                        //调取主树干的职责方法
            Console.Read();
        }
    }
    //公司类  抽象类或接口
    abstract class Company
    {  
        protected string name;
        public Company (string name)                                  //创建Company的构造函数
        {
            this.name = name;
        }
        public abstract void Add(Company c);                          //创建抽象类的Add()抽象方法
        public abstract void Remove(Company c);
        public abstract void Display(int depth);
        public abstract void LineOfDuty();
    }

    //具体公司类  实现接口 树枝节点
    class ConCreteCompany:Company
    {
        private   List<Company> children = new List<Company>();       //创建一个泛型集合,类型为Company类
        public ConCreteCompany(string name):base(name)                //继承父类的参数
        { }
        public override void Add(Company c)                           //重写父类的Add()方法
        {
            children.Add(c);                                          //调取集合的添加Add方法,将输入的内容添加到集合中
        }
        public override void Remove(Company c)                        //重写父类Remove()方法
        {
            children.Remove(c);                                       //移除集合中的内容
        }
        public override void Display(int depth)                       //重写父类Display()方法
        {
            Console.WriteLine(new string ( '-',depth)+name);          //在控制台上输入内容:此处的depth代表的是显示几个‘-’符号
            foreach (Company component  in children )                 //遍历children集合(主干树上的内容)
            {
                component.Display(depth + 2);                         //调取显示方法,参数为原传入的整数:1加上2,即显示三个“-”符号
            }
        }
        public override void LineOfDuty()                             //重写抽象类的职责方法
        {
            foreach (Company component in children )                  //遍历children集合,调取每个不同类的职责方法
            {
                component.LineOfDuty();
            }
        }
    //人力资源部与财务部类  树叶节点
    }
    class HRDepartment : Company
    {
        public HRDepartment(string name) : base(name)
        { }
        public override void Add(Company c)                           //叶节点不再长出新节点,所以此处的重写方法是无具体的方法体(透明方式),如果把这个去掉就是(安全方式)了
        { }
        public override void Remove(Company c)
        { }
        public override void Display(int depth)
        {
            Console.WriteLine(new string('-', depth) + name);
        }
        public override void LineOfDuty()                             //叶节点中的具体实现
        {
            Console.WriteLine("{0}  员工招聘培训管理", name);
        }
    }
    class FinanceDepartment : Company
    {
       ......(与DRDepartment类似)
    }

四、拓展

①、组合模式(很棒的文章)

http://www.cnblogs.com/goodboy-heyang/p/5226090.html

 https://www.cnblogs.com/jenkinschan/p/6071933.html

②、for循环与foreach区别

http://www.runoob.com/csharp/csharp-for-loop.html

以上便是组合模式的梳理,下一站走起O(∩_∩)O~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 15
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Elsa~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值