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

访问者设计模式

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.89/5 (21投票s)

2009年9月9日

CPOL

3分钟阅读

viewsIcon

81421

downloadIcon

610

本文展示了一个案例研究,关于我们如何在日托中心奖励系统中使用访问者模式。

背景

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

在之前的文章中,我讨论了如何使用策略模式来开发一个医生就诊系统。 在那种情况下,我只关注了Doctor 对象,以说明当策略对象(不同的医生)更改时,这些动态操作将如何受到影响。

在本文中,我将重点关注那些可访问/Kid 对象,这些对象由Doctors检查。

在伊丽莎白的日托中心日历上,显示王医生 (EyeDoctor) 每个月 15 号为所有孩子进行视力筛查,Fong 医生 (SLP - 语言病理学家) 每个月 28 号进行语言评估。 并且家长可以随时探望他们的孩子。

对于每次访问者的访问,在医生访问后,所有相关的状态都需要更新。 EyeDoctor 将仅更新EyeStatus,而 SLP 也会更新SpeechStatus。 家长将同时更新 EyeStatusSpeechStatus

请记住,孩子们可能会被不同的访问者访问。 它可以允许任何类型的访问者访问,但是,访问者应该知道在他们访问之后需要为孩子更新什么状态。

引言

访问者模式可以帮助我们解耦特定可访问对象的运算细节与多个访问者对象。 当这些对象需要为 visitableObject (Kid) 实现自己的逻辑时,我们将责任隔离在单独的访问者对象(例如 EyeDoctorSLPParent)中。

本文介绍了我们如何将访问者模式应用于我们的日托中心。

访问者设计模式结构

visitorS.JPG

类图

VisitorClass.JPG - Click to enlarge image

实现代码

访问者对象

访问者

Visitor 类是我们的基本 abstract 类。 这里声明了一个 abstract public 方法 (Visit) 以允许子类实现细节。 它将一个 VisitableObject 对象作为参数。 它实际上为子 Visitor 类提供了围绕它工作的能力。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace www.askbargains.com
{
    namespace VisitorDesignPattern
    {
        public abstract class Visitor
        {
            abstract public void Visit(VisitableObject akid);
        }
    }
}

眼科医生

在我的 EyeDoctor 类中,一个子 Visitor 类,它只会更新传入 visitableObjecteyestatus

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace www.askbargains.com
{
    namespace VisitorDesignPattern
    {
        public class EyeDoctor : Visitor
        {
            //Visit the visitableObject and update the deserved information
            public override void Visit(VisitableObject akid)
            {
                Kid kid = (Kid)akid;
                kid.EyeStatus = "Status updated from EyeDoctor - 
		Message from Dr.WANG, Eye Infections found for " + kid.Name + ". 
		Please schedule an appointment asap";
            }
        }
    }
}

SLP

EyeDoctor 相同,SLP 类将仅更新传入 visitableObjectSpeechstatus

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace www.askbargains.com
{
    namespace VisitorDesignPattern
    {
        public class SLP : Visitor
        {

            public override void Visit(VisitableObject akid)
            {
                Kid kid = (Kid)akid;
                kid.SpeechStatus = "Status updated from SLP - This is Dr.FONG, " + 
			kid.Name + " did a good job on the speech exam.";
            }
        }
    }
}

Parent

EyeDoctor 相同,Parent 类将同时更新传入 visitableObjectEyestatusSpeechstatus

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace www.askbargains.com
{
    namespace VisitorDesignPattern
    {
        public class Parent : Visitor
        {
            public override void Visit(VisitableObject akid)
            {
                Kid kid = (Kid)akid;
                kid.EyeStatus += Environment.NewLine + 
			"Status updated from Parent -- This is " + kid.Name + 
			"'s parent, I updated the EyeStatus.";
                kid.SpeechStatus += Environment.NewLine + 
			"Status updated from Parent -- This is " + kid.Name + 
			"'s parent, I updated the SpeechStatus.";
            }
        }
    }
}

VisitableObject 类

VisitableObject

VisitableObject 类是一个 abstract 基类,它有一个 public 方法 (AcceptVisitor)。 AcceptVisitor 方法是我们访问者模式中的关键方法。 它将一个 Visitor 对象作为参数,这将调用其 Visit 函数来访问它自己的 visitableObjectvisitableObject 的一个实例),以便实现访问模式。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace www.askbargains.com
{
    namespace VisitorDesignPattern
    {
        public abstract class VisitableObject
        {
            public void AcceptVisitor(Visitor visitor)
            {
                //allow the incoming visitor to start visiting
                visitor.Visit(this);
            }
        }
    }
}

Kid 类

这里的 Kid 类是一个从 VisitableObject 继承的辅助类。 它保存每个孩子的个人信息。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace www.askbargains.com
{
    namespace VisitorDesignPattern
    {
        public class Kid : VisitableObject
        {
            public string Name { get; set; }
            public int Age { get; set; }

            public string EyeStatus { get; set; }
            public string SpeechStatus { get; set; }
        }
    }
}

客户端应用程序

从客户端来看,我创建了两个孩子作为我们的 visitableObject 对象,并将它们添加到日托中心。 而且我还创建了一个访问者集合,它包含一个 EyeDoctor、一个 SLP 和一个 Parent。 对于每个孩子,她/他将受到来自访问者集合的每个访问者的访问。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using www.askbargains.com.VisitorDesignPattern;

namespace www.askbargains.com
{
    namespace Client
    {
        class Program
        {
            static void Main(string[] args)
            {
                List<kid> dayCare = new List<kid>();

                //Kid Elizabeth is created
                Kid Elizabeth = new Kid();
                Elizabeth.Name = "Elizabeth";
                Elizabeth.Age = 3;
                //add Elizabeth to daycare
                dayCare.Add(Elizabeth);

                //Kid Aimee is created
                Kid Aimee = new Kid();
                Aimee.Name = "Aimee";
                Aimee.Age = 4;
                //add Aimee to daycare
                dayCare.Add(Aimee);

                //create Visitors
                List<visitor> visitors = new List<visitor>();
                visitors.Add(new EyeDoctor());
                visitors.Add(new SLP());
                visitors.Add(new Parent());

                //start looping all the visitors
                foreach (Visitor visitor in visitors)
                {
                    //kid start to be visited for each visitor
                    foreach (Kid oneKid in dayCare)
                    {
                        oneKid.AcceptVisitor(visitor);
                    }
                }

                //display result
                foreach (Kid oneKid in dayCare)
                {
                    Console.WriteLine("Display Status for " + oneKid.Name);
                    Console.WriteLine(oneKid.EyeStatus);
                    Console.WriteLine(oneKid.SpeechStatus);
                    Console.ReadLine();
                }
                Console.ReadLine();
            }
        }
    }
}

一旦我们启动我们的客户端应用程序,您将看到在输出窗口中每次访问者访问后,对应的状态都已更新。 太棒了!

VisitorOutput.JPG

结论

从本文中,我展示了我们如何使用访问者模式来实现日托访问者的实现。 我还在 我的另一篇文章 中使用日托中心进行装饰器设计模式。

访问者设计模式 - CodeProject - 代码之家
© . All rights reserved.