组合模式更清晰的例子

设计模式系列-组合模式

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

       进到美发店,便有热情的服务生招呼,显示洗头,挑选造型师,开始剪发,剪发中被造型师推荐了各种各样的收费项目,我只选择了一样软化头发。完毕之后,看了 下单子哇塞、好贵噢,不过造型师给我剪的发型我还是很喜欢的,我决定以后还找他剪,但是又太贵,无奈中,发型师向我推荐了他们的会员卡,全场所有项目均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 吕津  

转载于:https://www.cnblogs.com/kexb/p/3668399.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值