65.9K
CodeProject 正在变化。 阅读更多。
Home

装饰器设计模式

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.73/5 (9投票s)

2009 年 9 月 2 日

CPOL

3分钟阅读

viewsIcon

57035

downloadIcon

252

本文展示了一个案例研究,说明了我们如何使用装饰器模式来实现日托中心的奖励系统。

背景

再次来到我最喜欢的地方 - 伊丽莎白的日托中心。

在伊丽莎白的日托中心,每周都为孩子们设立了许多奖励计划。 例如:每周结束时,根据孩子们的成就颁发三种类型的奖项。 根据孩子们每周的表现,孩子们可以获得不同的奖品。

  1. 所有孩子将在周末获得一张贴纸作为奖励。
  2. 如果孩子通过了如厕训练,则可以将证书张贴在他的/她的隔间上。
  3. 当孩子成为“本周之星”时,也可以获得一本免费书籍。

请记住,孩子们在周末可能会获得不同的奖品。 这实际上取决于孩子该周所做的事情。 这意味着每周都会动态地将奖励添加到孩子们,并且下周也可以将其删除。

引言

当我们尝试扩展特定活动的附加工作时,装饰器设计可能会有所帮助。 基于同一对象的不同级别(或条件),我们可能希望扩展同一方法的装饰。 例如:一个一岁的婴儿在高兴时会微笑。 一旦她2岁了,她可以微笑并跳起来表达她的快乐。 当她3岁时,她可以微笑,跳跃并在高兴时说话。 但是,从客户端的角度来看,客户端不会注意到使用对象时附加了哪些其他过程。 客户只知道婴儿很高兴,婴儿如何描述自己的快乐将取决于他的/她的年龄。

装饰器设计模式结构

Decorator.JPG

类图

Decorator_Class.JPG

实现代码

组件类

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(本周之星孩子)

PottyTrainedKidKidofWeek_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();
            }
        }
    }
}

执行客户端应用程序后,您可以看到伊丽莎白每周获得的所有奖品。 太酷了!

Decorator_output.JPG

结论

在本文中,我演示了如何使用装饰器模式来实现日托奖励系统。 在我的另一篇文章中,我还将日托中心用于职责链模式。

历史

  • 2009 年 9 月 2 日:首次发布。
© . All rights reserved.