设计模式系列-组合模式

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

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

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

    原文作者:王波洋
    原文地址: http://www.cnblogs.com/doubleliang/archive/2011/12/27/2304104.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞