您的位置:首页 > 其它

《Head First Design Patterns》笔记十四:复合模式(Compound Pattern)

2009-08-31 09:01 513 查看
概述

设计模式,GOF给出23个模式,《Head First Design
Patterns》主要描述了其中的13个模式。我们一般应用软件,很少有只用1中模式的,往往都是几个模式一起用。这就是复合模式。其实,我们在应用模
式的时候大概每个人都已经在使用复合模式了。

还是来看实例吧,主角我们还是选用可爱的鸭子,

模式应用实例

我们来做个鸭子模拟器吧

step 1
:首先是主角出场,红头鸦,绿头鸭,鸭鸣器,还有最拉风的橡皮鸭。有请(如下):



要求很简单,就需要会叫,就可以了,好,我们动手吧,先来接口IQuackable,然后逐一实现MallardDuck, RedHeadDuck, DuckCall, RubberDuck 就可以了。代码如下

IQuackable.cs 定义接口

using System;
namespace FUZHEPING.DesignPatterns.CompoundPatterns
{
interface IQuackable
{
void Quack();
}
}


MallardDuck.cs

using System;
namespace FUZHEPING.DesignPatterns.CompoundPatterns
{
class MallardDuck:IQuackable
{
public void Quack()
{
Console.WriteLine("Quack");
}
}
}


RedHeadDuck.cs

using System;
namespace FUZHEPING.DesignPatterns.CompoundPatterns
{
class RedHeadDuck:IQuackable
{
public void Quack()
{
Console.WriteLine("Quack");
}
}
}


DuckCall.cs

using System;
namespace FUZHEPING.DesignPatterns.CompoundPatterns
{
class DuckCall:IQuackable
{
public void Quack()
{
Console.WriteLine("Quack");
}
}
}


RubberDuck.cs

using System;
namespace FUZHEPING.DesignPatterns.CompoundPatterns
{
class RubberDuck:IQuackable
{
public void Quack()
{
Console.WriteLine("Squeack");
}
}
}


DuckSimulator.cs 实现鸭子模拟器

using System;
namespace FUZHEPING.DesignPatterns.CompoundPatterns
{
class Simulator
{
public static void SimDuck(IQuackable duck)
{
duck.Quack();
}
}
}


运行Program.cs

using System;
namespace FUZHEPING.DesignPatterns.CompoundPatterns
{
public class Program
{
public static void Main()
{
IQuackable mallardDuck=new MallardDuck();
IQuackable redHeadDuck=new RedHeadDuck();
IQuackable duckCall=new DuckCall();
IQuackable rubberDuck=new RubberDuck();
Simulator.SimDuck(mallardDuck);
Simulator.SimDuck(redHeadDuck);
Simulator.SimDuck(duckCall);
Simulator.SimDuck(rubberDuck);
}

}
}


运行结果如下:

Quack

Quack

Quack

Squeack

Step 2:适配器模式

上面模拟的很好,现在来个了不和谐的客人了,看,谁来了



鹅大妈可不会Quack Quack 叫,她只会Honk Honk,还会咬人,我小时候贼怕鹅,不过咬人这点这里就略过了

呵呵,那怎么办呢,是用适配器模式的时候了,

这里给出2段代码Goose.cs,GooseAdapter.cs

goose.cs

using System;
namespace FUZHEPING.DesignPatterns.CompoundPatterns
{
class Goose
{
public void Honk()
{
Console.WriteLine("Honk");
}
}

}


GooseAdapter.cs

using System;
namespace FUZHEPING.DesignPatterns.CompoundPatterns
{
class GooseAdapter:IQuackable
{
Goose _goose;
public GooseAdapter(Goose goose)
{
_goose=goose;
}
public void Quack()
{
_goose.Honk();
}
}
}


要创建Goose,只需要建立new GooseAdapter(new Goose()),就可以鱼目混珠,混在鸭子堆中。

Step 3:工厂模式

要做到简单,能不能让客户不需要操心怎么new的细节,而是直接调用呢,那就是工厂模式了。

先建立一个enum枚举类型

using System;
namespace FUZHEPING.DesignPatterns.CompoundPatterns
{
public enum Ducks
{
RedHeadDuck,MallardDuck,RubberDuck,DuckCall,Goose
}
}


然后创建工厂

using System;
namespace FUZHEPING.DesignPatterns.CompoundPatterns
{
class DuckFactory
{
public static  IQuackable CreateDuck(Ducks duck)
{
IQuackable quacker=null;
switch(duck)
{
case Ducks.RedHeadDuck:quacker=new RedHeadDuck();break;
case Ducks.MallardDuck:quacker=new MallardDuck();break;
case Ducks.RubberDuck:quacker=new RubberDuck();break;
case Ducks.DuckCall:quacker=new DuckCall();break;
case Ducks.Goose:quacker=new GooseAdapter(new Goose());break;
}
return quacker;
}
}
}


program如下

using System;
namespace FUZHEPING.DesignPatterns.CompoundPatterns
{
public class Program
{
public static void Main()
{
IQuackable mallardDuck=DuckFactory.CreateDuck(Ducks.MallardDuck);
IQuackable redHeadDuck=DuckFactory.CreateDuck(Ducks.RedHeadDuck);
IQuackable duckCall=DuckFactory.CreateDuck(Ducks.DuckCall);
IQuackable rubberDuck=DuckFactory.CreateDuck(Ducks.RubberDuck);
IQuackable goose=DuckFactory.CreateDuck(Ducks.Goose);
Simulator.SimDuck(mallardDuck);
Simulator.SimDuck(redHeadDuck);
Simulator.SimDuck(duckCall);
Simulator.SimDuck(rubberDuck);
Simulator.SimDuck(goose);
}

}
}


现在所有鸭子的创建部分由工厂负责了。

STEP 4:组合模式

现在有新的要求了,考虑鸭子太多了,不好管理,能不能让它们组成一个个组合,几只鸭子组成1队,多个队或单独鸭子也同样可以组队。

这样当模拟的时候,直接调用队列就可以了,而不需要一只只鸭子的调用。

ok,这就是组合模式了。

我们先来创建2个类,1个singleQuack,一个QuackArray

using System;
using System.Collections.Generic;
namespace FUZHEPING.DesignPatterns.CompoundPatterns
{
class SingleQuack:IQuackable
{
public List<IQuackable> Quackers
{
get{return null;}
}
public virtual void Quack()
{
Console.WriteLine("Quack");
}

}
}


QuackArray.cs:

using System;
using System.Collections.Generic;
namespace FUZHEPING.DesignPatterns.CompoundPatterns
{
class QuackArray:IQuackable
{
List<IQuackable> _quackers=new List<IQuackable>();
public List<IQuackable> Quackers
{
get{return _quackers;}
}
public void Quack()
{
foreach(IQuackable quacker in _quackers)
{
quacker.Quack();
}

}

}
}


这2个类都同时继承与IQuackable

然后我们改写鸭子的实现,以DuckCall为例,如下

using System;
namespace FUZHEPING.DesignPatterns.CompoundPatterns
{
class DuckCall:SingleQuack
{
}
}


Program.cs改写如下

using System;
namespace FUZHEPING.DesignPatterns.CompoundPatterns
{
public class Program
{
public static void Main()
{
IQuackable mallardDuck=DuckFactory.CreateDuck(Ducks.MallardDuck);
IQuackable redHeadDuck=DuckFactory.CreateDuck(Ducks.RedHeadDuck);
IQuackable duckCall=DuckFactory.CreateDuck(Ducks.DuckCall);
IQuackable rubberDuck=DuckFactory.CreateDuck(Ducks.RubberDuck);
IQuackable duckArray=new QuackArray();

duckArray.Quackers.Add(mallardDuck);
duckArray.Quackers.Add(redHeadDuck);
duckArray.Quackers.Add(duckCall);
duckArray.Quackers.Add(rubberDuck);
IQuackable goose1=DuckFactory.CreateDuck(Ducks.Goose);
IQuackable goose2=DuckFactory.CreateDuck(Ducks.Goose);
IQuackable goose3=DuckFactory.CreateDuck(Ducks.Goose);
IQuackable gooseArray=new QuackArray();
gooseArray.Quackers.Add(goose1);
gooseArray.Quackers.Add(goose2);
gooseArray.Quackers.Add(goose3);
duckArray.Quackers.Add(gooseArray);

Simulator.SimDuck(duckArray);
}

}
}


这里调用鸭子不再需要1个1个调用了,直接一句Simulator.SimDuck(duckArray)就搞定。

Step 5:装饰模式

现在老板又突发奇想了,要给每只鸭子装1个计数器,鸭子没叫1次,计数器就加1,最后需要知道所有鸭子总共叫了多少次。

ok,这是个新功能了。要给1件事务加新功能,新行为,用Decorator装饰者模式不错

我们来创建装饰品QuackCounter.cs

using System;
namespace FUZHEPING.DesignPatterns.CompoundPatterns
{
class QuackCounter:SingleQuack
{
SingleQuack _quacker;
static int _count;
public static int Count
{
get{return _count;}
}
public QuackCounter(SingleQuack quacker)
{
_quacker=quacker;
}
public override void Quack()
{
_count++;
_quacker.Quack();
}

}
}


在改写Factory

using System;
namespace FUZHEPING.DesignPatterns.CompoundPatterns
{
class DuckFactory
{
public static  SingleQuack CreateDuck(Ducks duck)
{
SingleQuack quacker=null;
switch(duck)
{
case Ducks.RedHeadDuck:quacker=new RedHeadDuck();break;
case Ducks.MallardDuck:quacker=new MallardDuck();break;
case Ducks.RubberDuck:quacker=new RubberDuck();break;
case Ducks.DuckCall:quacker=new DuckCall();break;
case Ducks.Goose:quacker=new GooseAdapter(new Goose());break;
}
return quacker;
}
public static SingleQuack  CreateCounterDuck(Ducks duck)
{
SingleQuack counterQuacker=new QuackCounter(CreateDuck(duck));
return counterQuacker;

}
}
}


当需要调用带计数器的鸭子的时候,直接调用CreateCounterDuck(...)

Step 5:观察者模式

新需求来了。我们的鸭子专家现在需要远程监控鸭子的行为。每当鸭子叫一下,专家就即时获得消息,ok,这就是事件了,鸭子一叫就触发了事件。这根本也就是观察者模式。

我们现在要给所有鸭子加上事件了,那就是改鸭子的父类了

首先修改接口IQuackable,给接口加上event

using System;
using System.Collections.Generic;
namespace FUZHEPING.DesignPatterns.CompoundPatterns
{
public delegate void QuackHandle(IQuackable quacker);
public interface IQuackable
{
event  QuackHandle OnQuack;
List<IQuackable> Quackers	{	get;	}
void Quack();
}
}


然后鸭子父类SingleDuck.cs

using System;
using System.Collections.Generic;
namespace FUZHEPING.DesignPatterns.CompoundPatterns
{

class SingleQuack:IQuackable
{

public  virtual event QuackHandle OnQuack;

public List<IQuackable> Quackers
{
get{return null;}
}

public virtual void Quack()
{
Console.WriteLine("Quack");
DoEvent();
}
protected void DoEvent()
{
if (OnQuack!=null) OnQuack(this);
}

}
}


在就是鸭子组合QuackArray了,注意,这里鸭子组合当注册事件的时候,实际上是给所有组合里的鸭子/鸭子组 注册事件

如下

using System;
using System.Collections.Generic;
namespace FUZHEPING.DesignPatterns.CompoundPatterns
{
class QuackArray:IQuackable
{
List<IQuackable> _quackers=new List<IQuackable>();
public event QuackHandle OnQuack
{
add
{
foreach(IQuackable quacker in _quackers)
{
quacker.OnQuack+=value;
}
}
remove
{
foreach(IQuackable quacker in _quackers)
{
quacker.OnQuack-=value;
}
}
}
public List<IQuackable> Quackers
{
get{return _quackers;}
}
public void Quack()
{
foreach(IQuackable quacker in _quackers)
{
quacker.Quack();
}
}

}
}


还有就是QuackCounter了,别忘了给它重写事件,这里counter注册事件的时候,实际上是给鸭子本体注册时间,而不是这个装饰品。

如下:

using System;
namespace FUZHEPING.DesignPatterns.CompoundPatterns
{
class QuackCounter:SingleQuack
{
SingleQuack _quacker;
public override event QuackHandle OnQuack
{
add
{
_quacker.OnQuack+=value;
}
remove
{
_quacker.OnQuack-=value;
}
}
static int _count;
public static int Count
{
get{return _count;}
}
public QuackCounter(SingleQuack quacker)
{
_quacker=quacker;
}
public override void Quack()
{
_count++;
_quacker.Quack();
}
public override string ToString()
{
return  _quacker.ToString()+" with counter ";
}

}
}


Program.cs如下

using System;
namespace FUZHEPING.DesignPatterns.CompoundPatterns
{
public class Program
{
public static void Main()
{
IQuackable mallardDuck=DuckFactory.CreateCounterDuck(Ducks.MallardDuck);
IQuackable redHeadDuck=DuckFactory.CreateCounterDuck(Ducks.RedHeadDuck);
IQuackable duckCall=DuckFactory.CreateCounterDuck(Ducks.DuckCall);
IQuackable rubberDuck=DuckFactory.CreateCounterDuck(Ducks.RubberDuck);
rubberDuck=new RubberDuck();
IQuackable duckArray=new QuackArray();

duckArray.Quackers.Add(mallardDuck);
duckArray.Quackers.Add(redHeadDuck);
duckArray.Quackers.Add(duckCall);
duckArray.Quackers.Add(rubberDuck);
IQuackable goose1=DuckFactory.CreateCounterDuck(Ducks.Goose);
IQuackable goose2=DuckFactory.CreateCounterDuck(Ducks.Goose);
IQuackable goose3=DuckFactory.CreateCounterDuck(Ducks.Goose);

IQuackable gooseArray=new QuackArray();
gooseArray.Quackers.Add(goose1);
gooseArray.Quackers.Add(goose2);
gooseArray.Quackers.Add(goose3);
duckArray.Quackers.Add(gooseArray);

Quackologist quackologist=new  Quackologist();
duckArray.OnQuack+= quackologist.ShowQuackInfo;
Simulator.SimDuck(duckArray);
Console.WriteLine("the count of quack is {0}",QuackCounter.Count);

}

}
}


结果:

Quack

FUZHEPING.DesignPatterns.CompoundPatterns.MallardDuck just quacked

Quack

FUZHEPING.DesignPatterns.CompoundPatterns.RedHeadDuck just quacked

Quack

FUZHEPING.DesignPatterns.CompoundPatterns.DuckCall just quacked

Squeack

FUZHEPING.DesignPatterns.CompoundPatterns.RubberDuck just quacked

Honk

FUZHEPING.DesignPatterns.CompoundPatterns.GooseAdapter just quacked

Honk

FUZHEPING.DesignPatterns.CompoundPatterns.GooseAdapter just quacked

Honk

FUZHEPING.DesignPatterns.CompoundPatterns.GooseAdapter just quacked

the count of quack is 6

下一篇:《Head First Design Patterns》笔记十五:MVC

上一篇:《Head First Design Patterns》笔记十三:代理模式(Proxy Pattern)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: