【问题标题】:Observer Pattern and Delegates观察者模式和委托
【发布时间】:2009-04-21 23:50:25
【问题描述】:

我需要帮助来尝试理解观察者模式和代表。我在另一个网站上找到了这段代码,我试图了解它实际上在做什么。谁能帮帮我。

当我执行代码时,我收到两条消息“服务器已启动并正在运行”和“服务器已关闭,我们正在处理它,它很快就会恢复”。我想我收到了两条消息,因为在 Main 中有一个 server.ServerStatus = true;和 server.ServerStatus = false。但是,如果我注释掉 server.ServerStatus = true;然后运行,我收到消息“服务器已启动并正在运行”,但我预计只会看到“服务器已关闭,我们正在处理它,它很快就会回来。”。有人可以解释吗? 苏珊

class Program
{
    static void Main(string[] args)
    {
        Server server = new Server();
        server.ServerStatusChanged += new EventHandler(ProcessServerStatus);
        server.ServerStatus = true; 
        server.ServerStatus = false;
        Console.Read();
    }


    public class Server
    {
        public event EventHandler ServerStatusChanged;
        private bool _ServerStatus;

        public bool ServerStatus
        {
            get { return this._ServerStatus; }
            set {
                if (this._ServerStatus == value) return; // Dont need to do anything;
                if (this.ServerStatusChanged != null) // make sure the invocation list is not empty  
                    ServerStatusChanged(value, new EventArgs());  // Firing Event
                this._ServerStatus = value; 
            } 
        }
    }



    public static void ProcessServerStatus(object sender, EventArgs e)
    {
        bool status = (bool)sender; 
        if (status)
            Console.WriteLine("Server is up and running");
        else
            Console.WriteLine("Server is down, We are working on it it will be back soon");

    }



}

【问题讨论】:

  • 这是标记为Java,但我认为代码实际上是C#。
  • 确实,那些 get{} set{} :s 是 C# 的功能,而不是 Java。更改了标签。

标签: c# observer-pattern


【解决方案1】:

这里有你想要的代码。

注意 _initialized 变量。这是必需的,因为否则第一次不会发生任何事情。在它开始正常工作之前,您必须将状态设置为 True。

另外,你所描述的我并没有发生。我没有收到消息说它已启动并正在运行。我什么都没得到。

    class Program
{
    static void Main(string[] args)
    {
        Server server = new Server(); 
        server.ServerStatusChanged += new EventHandler(ProcessServerStatus); 
        //server.ServerStatus = true; 
        server.ServerStatus = false; 
        Console.Read();
    }

    public class Server
    {
        public event EventHandler ServerStatusChanged; 
        private bool _ServerStatus = false;
        private bool _initialized = false;
        public bool ServerStatus
        {
            get { return this._ServerStatus; }
            set
            {
                if (this._initialized == true && this._ServerStatus == value)
                    return; // Dont need to do anything;                
                else
                    this._initialized = true;
                if (this.ServerStatusChanged != null) // make sure the invocation list is not empty                      
                    ServerStatusChanged(value, new EventArgs());  // Firing Event                
                this._ServerStatus = value;
            }
        }
    }
    public static void ProcessServerStatus(object sender, EventArgs e)
    {
        bool status = (bool)sender;
        if (status)
            Console.WriteLine("Server is up and running");
        else Console.WriteLine("Server is down, We are working on it it will be back soon");
    }
}

【讨论】:

  • 如果不初始化 ServerStatus 值,我认为您会得到不可预知的结果,即“服务器正在运行...”,而且由于设置器只是有条件地调用 ProcessServerStatus 方法,所以您没有得到“SErver已关闭...”消息
【解决方案2】:

这是一个活动注册...

server.ServerStatusChanged += new EventHandler(ProcessServerStatus);

它说“只要有 ServerStatusChanged,就调用 ProcesServerStatus 方法。”因此,当您将 ServerStatus 设置为 true 时,您会调用 ProcessServerStatus 并传递 true 并打印“Server is up...”;当您将其更改为 false 时,会触发另一个事件,但这次 ServerStatus 为 false,因此您会得到“服务器已关闭 ...”因此,您正在监视服务器状态并在它更改时执行某些操作 (ProcessServerStatus)。

【讨论】:

    【解决方案3】:

    基本上发生的情况是,您在 Main 中将 ServerStatus 设置为 true/false 的分配将调用 ServerStatus 属性的“设置”函数。

    在该函数中,将创建一个事件并将其触发到 ServerStatusChanged 处理程序,任何注册事件的人都将收到该事件。另请注意,仅当状态更改时才会触发该事件。

    在这种情况下,Main 为

    中的事件注册了
    Server.ServerStatusChanged += new EventHandler(ProcessServerStatus);
    

    行。

    由于您将 ServerStatus 设置为 true,然后在 Main 中设置为 false,因此会触发两个事件,导致您的控制台同时显示“服务器已启动并正在运行”和“服务器已关闭,我们正在处理它....”

    【讨论】:

      【解决方案4】:

      如果您以前没有接触过观察者模式,可能会本能地认为所有方法调用都是静态完成的——我们在代码中调用的方法就是被调用的方法。然而,观察者模式可以让你更动态地做事。您可以在运行时说“嘿,当某某发生时,请告诉我!您可以通过调用某某方法让我知道”被观察的人会记录所有对它说过的人“当这种情况发生时发生这种情况,让我知道”——然后,当它发生时,它就是这么做的——让所有人都知道。这是通过保留必须调用的方法列表来完成的,然后在事件“触发”时调用它们。

      行:

      server.ServerStatusChanged += new EventHandler(ProcessServerStatus);
      

      正在告诉服务器对象“嘿,当服务器状态发生变化时,请告诉我。你可以通过调用 ProcessServerStatus 方法让我知道”。所以,当行:

      server.ServerStatus = true;
      

      运行时,它会触发 ServerStatusChanged 事件,然后调用所有“让我知道”的内容。所以它会调用ProcessServerStatus 方法,因为这是它列表中唯一的方法。

      该列表中的每个方法都必须具有特定的方法签名;在这种情况下,void ProcessServerStatus(object sender, EventArgs e)。在这种情况下,sender 参数是服务器状态 - 您可以在以下行中看到:

      ServerStatusChanged(value, new EventArgs());
      

      所以当ProcessServerStatus 被调用时,它会将其转换为布尔值,并打印出相应的字符串。

      当我运行此代码时,它按预期工作 - 如果我注释掉 serverStatus = true; 行,它不会打印任何内容(因为 _serverStatus 默认为 false,并且如果状态没有更改,则不会触发事件)。相反,如果我注释掉 serverStatus = false; 行,它会显示“服务器已启动并正在运行”

      【讨论】:

        猜你喜欢
        • 2011-03-07
        • 2010-11-04
        • 1970-01-01
        • 2016-02-20
        • 2023-04-10
        • 1970-01-01
        • 2023-03-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多