装饰器设计模式






4.73/5 (9投票s)
本文展示了一个案例研究,说明了我们如何使用装饰器模式来实现日托中心的奖励系统。
背景
再次来到我最喜欢的地方 - 伊丽莎白的日托中心。
在伊丽莎白的日托中心,每周都为孩子们设立了许多奖励计划。 例如:每周结束时,根据孩子们的成就颁发三种类型的奖项。 根据孩子们每周的表现,孩子们可以获得不同的奖品。
- 所有孩子将在周末获得一张贴纸作为奖励。
- 如果孩子通过了如厕训练,则可以将证书张贴在他的/她的隔间上。
- 当孩子成为“本周之星”时,也可以获得一本免费书籍。
请记住,孩子们在周末可能会获得不同的奖品。 这实际上取决于孩子该周所做的事情。 这意味着每周都会动态地将奖励添加到孩子们,并且下周也可以将其删除。
引言
当我们尝试扩展特定活动的附加工作时,装饰器设计可能会有所帮助。 基于同一对象的不同级别(或条件),我们可能希望扩展同一方法的装饰。 例如:一个一岁的婴儿在高兴时会微笑。 一旦她2岁了,她可以微笑并跳起来表达她的快乐。 当她3岁时,她可以微笑,跳跃并在高兴时说话。 但是,从客户端的角度来看,客户端不会注意到使用对象时附加了哪些其他过程。 客户只知道婴儿很高兴,婴儿如何描述自己的快乐将取决于他的/她的年龄。
装饰器设计模式结构
类图
实现代码
组件类
Kid(孩子)
Kid
类是一个abstract
抽象的基组件,它具有一个abstract
抽象方法来显示孩子的所有奖品。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace www.askbargains.com
{
namespace Decorator
{
public abstract class Kid
{
public string Name { get; set; }
public abstract void ShowMyPrizes();
}
}
}
GoodKid(好孩子)
GoodKid
是从Kid
类继承的具体组件类。 它实际上为ShowMyPrizes()
提供了默认实现。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace www.askbargains.com
{
namespace Decorator
{
//Concreate Kid
public class GoodKid : Kid
{
public override void ShowMyPrizes()
{
Console.WriteLine("My name is {0} .
I am a good kid! I get a sticker this week", Name);
}
}
}
}
装饰器类
KidDecorator(孩子装饰器)
KidDecorator
包含一个Kid
对象,该对象将允许Decorator
类扩展默认方法(在本例中为ShowMyPrizes()
)。 这是一个abstract
抽象类,仅提供基本协议; 必须开发一个具体的Decorator
类来实现扩展详细信息。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace www.askbargains.com
{
namespace Decorator
{
public abstract class KidDecorator : Kid
{
//an instance of kid.
Kid aKid;
public KidDecorator(Kid kid)
{
aKid = kid;
}
//show the deafult prize for aKid object
public override void ShowMyPrizes()
{
aKid.ShowMyPrizes();
}
}
}
}
PottyTrainedKid(如厕训练孩子)和 KidofWeek_Kid(本周之星孩子)
PottyTrainedKid
和KidofWeek_Kid
是将附加工作插入到默认方法中的具体Decorator
类。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace www.askbargains.com
{
namespace Decorator
{
public class PottyTrainedKid : KidDecorator
{
public PottyTrainedKid(Kid aKid)
: base(aKid)
{
}
public override void ShowMyPrizes()
{
//call base(deafault) method.
base.ShowMyPrizes();
//addtional method
ShowMyExtendPrize();
}
private void ShowMyExtendPrize()
{
Console.WriteLine("Since I am a potty trained kid, " +
"I also have an certificate stamped on my cube for this week");
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace www.askbargains.com
{
namespace Decorator
{
public class KidofWeek_Kid : KidDecorator
{
public KidofWeek_Kid(Kid aKid)
: base(aKid)
{
}
public override void ShowMyPrizes()
{
//call base(deafault) method.
base.ShowMyPrizes();
//addtional method
ShowMyAdditionalPrize();
}
private void ShowMyAdditionalPrize()
{
Console.WriteLine("Since I am a kid of this month, I also " +
"have a free book as a prize for this week");
}
}
}
}
客户端应用程序
从我的客户端应用程序中,我模拟了一个用例如下。
第一周,伊丽莎白只是一个好孩子。 第二周,伊丽莎白通过了如厕训练计划。 第三周,伊丽莎白通过了如厕训练计划,并且还成为了kidofweek
。 第四个月,她再次成为kidofweek
,但没有再次通过如厕训练。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using www.askbargains.com.Decorator;
namespace www.askbargains.com
{
namespace Client
{
class Program
{
static void Main(string[] args)
{
//Kid Elizabeth is created
GoodKid Elizabeth = new GoodKid();
Elizabeth.Name = "Elizabeth";
//First week. Elizabeth is a good kid only. She deserve her default prize.
DisplayReport(Elizabeth, "This is first week.");
//In the second week, Elizabeth pass the potty training.
Kid pottyKid = new PottyTrainedKid(Elizabeth);
DisplayReport(pottyKid, "This is second week.");
//In the third week, Elizabeth is both potty trained
//and kid of the week,
//She will have default , potty trained and kidofweek prizes.
Kid kidofweek = new KidofWeek_Kid(pottyKid);
DisplayReport(kidofweek, "This is third week.");
//In the four week, Elizabeth is kid of the week,
//She will have default and kidofweek prizes.
Kid newKid = new KidofWeek_Kid(Elizabeth);
DisplayReport(newKid, "This is fourth week.");
Console.Read();
}
//Helper method to show the report.
private static void DisplayReport(Kid anyKid, string weekMessage)
{
Console.WriteLine(weekMessage);
anyKid.ShowMyPrizes();
}
}
}
}
执行客户端应用程序后,您可以看到伊丽莎白每周获得的所有奖品。 太酷了!
结论
在本文中,我演示了如何使用装饰器模式来实现日托奖励系统。 在我的另一篇文章中,我还将日托中心用于职责链模式。
历史
- 2009 年 9 月 2 日:首次发布。