《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 定义接口
MallardDuck.cs
RedHeadDuck.cs
DuckCall.cs
RubberDuck.cs
DuckSimulator.cs 实现鸭子模拟器
运行Program.cs
运行结果如下:
Quack
Quack
Quack
Squeack
Step 2:适配器模式
上面模拟的很好,现在来个了不和谐的客人了,看,谁来了
鹅大妈可不会Quack Quack 叫,她只会Honk Honk,还会咬人,我小时候贼怕鹅,不过咬人这点这里就略过了
呵呵,那怎么办呢,是用适配器模式的时候了,
这里给出2段代码Goose.cs,GooseAdapter.cs
goose.cs
GooseAdapter.cs
要创建Goose,只需要建立new GooseAdapter(new Goose()),就可以鱼目混珠,混在鸭子堆中。
Step 3:工厂模式
要做到简单,能不能让客户不需要操心怎么new的细节,而是直接调用呢,那就是工厂模式了。
先建立一个enum枚举类型
然后创建工厂
program如下
现在所有鸭子的创建部分由工厂负责了。
STEP 4:组合模式
现在有新的要求了,考虑鸭子太多了,不好管理,能不能让它们组成一个个组合,几只鸭子组成1队,多个队或单独鸭子也同样可以组队。
这样当模拟的时候,直接调用队列就可以了,而不需要一只只鸭子的调用。
ok,这就是组合模式了。
我们先来创建2个类,1个singleQuack,一个QuackArray
QuackArray.cs:
这2个类都同时继承与IQuackable
然后我们改写鸭子的实现,以DuckCall为例,如下
Program.cs改写如下
这里调用鸭子不再需要1个1个调用了,直接一句Simulator.SimDuck(duckArray)就搞定。
Step 5:装饰模式
现在老板又突发奇想了,要给每只鸭子装1个计数器,鸭子没叫1次,计数器就加1,最后需要知道所有鸭子总共叫了多少次。
ok,这是个新功能了。要给1件事务加新功能,新行为,用Decorator装饰者模式不错
我们来创建装饰品QuackCounter.cs
在改写Factory
当需要调用带计数器的鸭子的时候,直接调用CreateCounterDuck(...)
Step 5:观察者模式
新需求来了。我们的鸭子专家现在需要远程监控鸭子的行为。每当鸭子叫一下,专家就即时获得消息,ok,这就是事件了,鸭子一叫就触发了事件。这根本也就是观察者模式。
我们现在要给所有鸭子加上事件了,那就是改鸭子的父类了
首先修改接口IQuackable,给接口加上event
然后鸭子父类SingleDuck.cs
在就是鸭子组合QuackArray了,注意,这里鸭子组合当注册事件的时候,实际上是给所有组合里的鸭子/鸭子组 注册事件
如下
还有就是QuackCounter了,别忘了给它重写事件,这里counter注册事件的时候,实际上是给鸭子本体注册时间,而不是这个装饰品。
如下:
Program.cs如下
结果:
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)
设计模式,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)
相关文章推荐
- 《Head First Design Patterns》笔记二:观察者模式(Observer Pattern)
- Head First Design patterns笔记-Observer Patterns (从TFS的Project alerts功能看观察者模式)
- Head First Design patterns笔记-Decorator Patterns (从”用不同技能武装自己”看装饰模式)
- 《Head First Design Patterns》笔记八:外观模式(Facade Pattern)
- Head First Design patterns笔记-Strategy Patterns (从不同的人使用不同的交通工具上班看策略模式)
- Head First Design patterns笔记-Singleton patterns (从“一夫一妻制社会中婚约的达成”看单件模式)
- 《Head First Design Patterns》笔记十二:状态模式(State Pattern)
- 复合模式——Head First Design Patterns
- 状态模式——Head First Design Patterns
- 中介者模式——Head First Design Patterns
- OOP Design (Head First Design Patterns) 学习笔记--04 The decorator pattern
- 《Head First Design Patterns》笔记四:工厂模式(Factory Pattern)
- 《Head First Design Patterns》读书笔记之观察者模式
- Head First Design Patterns(深入浅出设计模式)-目录
- Head First Design Patterns深入浅出设计模式(影印版)
- 建造者模式——Head First Design Patterns
- 解释器模式——Head First Design Patterns
- OOP Design (Head First Design Patterns) 学习笔记--01 SimUDuck app
- Head First Design Patterns 阅读笔记之二: Observer Pattern
- 模板方法模式——Head First Design Patterns