zoukankan      html  css  js  c++  java
  • 组合模式更清晰的例子

    设计模式系列-组合模式

          今天下班客厅的灯确实亮堂了许多,照照镜子感觉自己一下苍老许多,看来还是灯光暗比较好,看不出来自己的憔悴啊,哈哈,其实还是头发长了,决定出去剪发。

           进到美发店,便有热情的服务生招呼,显示洗头,挑选造型师,开始剪发,剪发中被造型师推荐了各种各样的收费项目,我只选择了一样软化头发。完毕之后,看了 下单子哇塞、好贵噢,不过造型师给我剪的发型我还是很喜欢的,我决定以后还找他剪,但是又太贵,无奈中,发型师向我推荐了他们的会员卡,全场所有项目均5 折,最近因为圣诞节还在搞活动这期间办卡的可享受折上折8.6,我心想那这下就太划算了,而且他们总店,分店都可以用,所以毫不犹豫的办了张会员卡。。。 囧。。。。

           到家后稍微有点后悔,我竟然一时冲动花了那么多钱办了张剪发的会员卡,不过办也办了,只好自己安慰安慰自己,心想,办了卡可以打折上折,而且那么多分店想 去哪家去哪家,顿时心情好为能好一点了,突然间想到了一个模式,跟现在的场景很合适,名字叫《组合模式》,为什么说跟组合模式很相似呢?

           先看看组合模式的定义吧,在《大话设计模式一书中》组合模式的定义为:“将对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

           那就拿我剪发办卡的事情来分析一下吧。

           首先,一张卡可以在总部,分店,加盟店使用,那么总部可以刷卡,分店也可以刷卡,加盟店也可以刷卡,这个属性结构的店面层级关系就明确啦。

           那么,总店刷卡消费与分店刷卡消费是一样的道理,那么总店与分店对会员卡的使用也具有一致性。

          1.组合模式的例子

            组合模式结构图:

            那么组合模式的实例如下:

    复制代码
     //抽象的部件类描述将来所有部件共有的行为
        public abstract class Component
        {
            protected string name;
            public string Name
            {
                get
                {
                    return name;
                }
                set
                {
                    name = value;
                }
            }
            //添加部件
            public abstract void Add(Component component);
            //删除部件
            public abstract void Remove(Component component);
            //遍历所有子部件
            public abstract void eachChild();
        }

        //组合部件类
        public class Leaf : Component
        {
            //叶子节点不具备添加的能力,所以不实现
            public override void Add(Component component)
            {
                throw new NotImplementedException();
            }

            //叶子节点不具备添加的能力必然也不能删除
            public override void Remove(Component component)
            {
                throw new NotImplementedException();
            }

            //叶子节点没有子节点所以显示自己的执行结果
            public override void eachChild()
            {
                Console.WriteLine("{0}执行了..",name);
            }
        }

        //组合类
        public class Composite : Component
        {
            //用来保存组合的部件
            List<Component> myList = new List<Component>();

            //添加节点 添加部件
            public override void Add(Component component)
            {
                myList.Add(component);
            }

            //删除节点 删除部件
            public override void Remove(Component component)
            {
                myList.Remove(component);
            }

            //遍历子节点
            public override void eachChild()
            {
                Console.WriteLine("{0}执行了..", name);
                foreach (Component c in myList)
                {
                    c.eachChild();
                }
            }
        }
        static void Main(string[] args)
        {
                //构造根节点
                Composite rootComponent = new Composite();
                rootComponent.Name = "根节点";

                //添加两个叶子几点,也就是子部件
                Leaf l = new Leaf();
                l.Name = "叶子节点一";
                Leaf l1 = new Leaf();
                l1.Name = "叶子节点二";

                rootComponent.Add(l);
                rootComponent.Add(l1);

                //遍历组合部件
                rootComponent.eachChild();
         }
    复制代码

            运行结果如下:

         

          2.应用组合模式的会员卡消费

            那么我们就根据我们会员卡的消费,来模拟一下组合模式的实现吧!let's go!

            首先:

                   1.我们的部件有,总店,分店,加盟店!

                   2.我们的部件共有的行为是:刷会员卡

                   3.部件之间的层次关系,也就是店面的层次关系是,总店下有分店、分店下可以拥有加盟店。

            有了我们这几个必要条件后,我的要求就是目前店面搞活动当我在总店刷卡后,就可以累积相当于在所有下级店面刷卡的积分总额,设计的代码如下:

    复制代码
     /// <summary>
        
    /// 店面类 抽象出来的店面部件
        
    /// </summary>
        public abstract class Storefront
        {
            //店名
            protected string storeName = string.Empty;
            public string StoreName
            {
                get
                {
                    return storeName;
                }
            }

            //添加店面
            public abstract void Add(Storefront store);
            //删除店面
            public abstract void Remove(Storefront store);

            //定义所有部件公用的行为 刷卡行为
            public abstract void PayByCard();
        }

        public class StoreOrBranch : Storefront
        {
            //构造函数
            public StoreOrBranch() { }
            public StoreOrBranch(string storeName)
            {
                this.storeName = storeName;
            }
            List<Storefront> myStoreList = new List<Storefront>();
            //刷卡消费
            public override void PayByCard()
            {
                Console.WriteLine("店面{0}的积分已累加进该会员卡", storeName);
                foreach (Storefront sf in myStoreList)
                {
                    sf.PayByCard();
                }
            }

            //增加店面
            public override void Add(Storefront store)
            {
                myStoreList.Add(store);
            }

            //解除店面
            public override void Remove(Storefront store)
            {
                myStoreList.Remove(store);
            }
        }

        public class JoinInStore : Storefront
        {
            //构造函数
            public JoinInStore() { }
            public JoinInStore(string storeName)
            {
                this.storeName = storeName;
            }
            //刷卡消费
            public override void PayByCard()
            {
                Console.WriteLine("店面{0}的积分已累加进该会员卡", storeName);
            }

            public override void Add(Storefront store)
            {
                throw new NotImplementedException();
            }

            public override void Remove(Storefront store)
            {
                throw new NotImplementedException();
            }
        }

       static void Main(string[] args)
       {
                StoreOrBranch store = new StoreOrBranch("朝阳总店");
                StoreOrBranch brach = new StoreOrBranch("东城分店");
                JoinInStore jstore = new JoinInStore("海淀加盟店一");
                JoinInStore jstore1 = new JoinInStore("上地加盟店二");

                brach.Add(jstore);
                brach.Add(jstore1);
                store.Add(brach);

                store.PayByCard();
        }
    复制代码

          运行结果如下:

          

           这样在累积所有子店面积分的时候,就不需要去关心子店面的个数了,也不用关系是否是叶子节点还是组合节点了,也就是说不管是总店刷卡,还是加盟店刷卡,都可以正确有效的计算出活动积分。

          3.什么情况下使用组合模式

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

     
    posted @ 2011-12-27 22:46 王波洋 阅读(5685) 评论(10) 编辑 收藏
    #1楼 2011-12-28 08:56 zjhzjh  
    写的很好,楼主是准备写设计模式的系列文章吗?
    #2楼[楼主] 2011-12-28 09:14 王波洋  
    @zjhzjh
    谢谢 支持,是的现在正在写C#系列和设计模式系列,两个系列并行写,偶尔写一些开发中的技巧和经验,主要还是写系列文章。呵呵
    以后还会写的系列文章,还有ASP.NET SQLSERVER js c++/asm系列的。
    C++/ASM 这个系列主要是用 VC++6.0 来讲述C++,并且用汇编展示C++背后所做的事情.. 这个系列还是比较精彩的噢..
    再次感谢支持.
    #3楼 2011-12-28 10:58 dongguojun  
    我比较关心你是去哪理发的,最近为理发发愁呢,头发都留长了,但是不知道去哪理发好。
    #4楼[楼主] 2011-12-28 11:18 王波洋  
    @dongguojun
    丽锦美容美发
    http://s.baidu.com/search/?hoi=459999fe1139572a18ea9ea9&ci=131
    哈哈,喜欢可以联系我 我有会员卡 打折。
    #5楼 2011-12-28 11:20 Stephen_Liu  
    设计模式的文章是非常好不好写的,他的难度不在于理论和解释,而是在理解和驾驭。
    #6楼[楼主] 2011-12-28 11:25 王波洋  
    @Stephen_Liu
    是的,我很赞同,我会尽最大努力来写这个系列,不到位的地方还请多多批评。
    #7楼 2012-04-22 16:46 Pato'  
    写的很好~
    #8楼 2013-05-24 18:33 freewind_zk  
    不错,基本上理解啦
    #9楼 2013-07-09 14:29 web开发初级  
    在我的眼中,设计模式怎么如脱光衣服的女人一个样!!! 多态,接口,仅此而已
    #10楼 2013-09-25 22:18 吕津  
  • 相关阅读:
    bzoj 1176 cdq分治套树状数组
    Codeforces 669E cdq分治
    Codeforces 1101D 点分治
    Codeforces 1100E 拓扑排序
    Codeforces 1188D Make Equal DP
    Codeforces 1188A 构造
    Codeforces 1188B 式子转化
    Codeforces 1188C DP 鸽巢原理
    Codeforces 1179D 树形DP 斜率优化
    git commit -m "XX"报错 pre -commit hook failed (add --no-verify to bypass)问题
  • 原文地址:https://www.cnblogs.com/kexb/p/3668399.html
Copyright © 2011-2022 走看看