【问题标题】:Observer pattern in C# / how to make a Form an observerC# 中的观察者模式/如何使表单成为观察者
【发布时间】:2013-11-13 11:05:08
【问题描述】:

到目前为止我还没有找到答案,可能只是缺少合适的关键字来搜索。

我想在 C# 中实现一个观察者模式,所以任何观察者对象都可以订阅一个主题对象,然后接收它的所有通知。然后它根据 Notification 类型决定它是否重要。

    public class Subject
{
    private List<Observer> observers;

    public void AttachObserver(Observer Observer)
    {
        this.observers.Add(Observer);
    }
    public void DetachObserver(Observer Observer)
    {
        this.observers.Remove(Observer);
    }
    public void NotifyObservers(CommonNotification Notification) // who we are, what kind of notification, bla bla
    {
        foreach(Observer Observer in observers)
        {
            Observer.OnNotify(Notification);
        }
    }
}

public class Observer
{
    public abstract void OnNotify(CommonNotification Notification);
}

所以任何想要订阅 Subject 的对象都需要继承 Observer 类。但是怎么做呢?我的 MainForm 是基于 Form 的。如果我将 Observer 类替换为通用对象,它将不会实现 OnNotify() 事件。

我在这里缺少什么?我知道我应该使用事件处理程序正确实现它,但为了了解基本设计模式的工作原理,我宁愿先自己实现。

【问题讨论】:

  • 使用接口代替抽象类
  • 你读过this吗?
  • 您知道观察者模式已经完全集成到 C# 语言中了吗?使用 event 关键字。你的 AttachObserver 是 +=,DetachObserver 是 -=,NotifyObservers 是 ()。

标签: c# design-patterns inheritance observer-pattern


【解决方案1】:

简答:看看这个问题的第一个答案:Super-simple example of C# observer/observable with delegates

我知道您想尝试自己实现它,但委托和事件在这里真的很自然(实际上是 C# 中内置的观察者模式的实现)。

如果仍想自己做,我建议使用接口而不是抽象/具体类。

public interface ISubject
{
    void AttachObserver(IObserver observer);
    void DetachObserver(IObserver observer);

    void NotifyObservers(CommonNotification Notification);
}

public interface IObserver
{
    void OnNotify(CommonNotification Notification);
}

然后您的表单可以实现 IObserver(或 ISubject 或两者兼有!!)。

public class MyForm : Form, IObserver
{
...
}

【讨论】:

    【解决方案2】:

    你可以像这样使用接口代替抽象类

    public Interface IObserver
    {
        public void OnNotify(CommonNotification Notification);
    }
    
    ....
    
    public class MyForm:Form, IObserver {
    ....
    }
    

    【讨论】:

      【解决方案3】:

      你应该用一个接口替换你的观察者类:

      public Interface IObserver
      {
          public void OnNotify(CommonNotification Notification);
      }
      

      然后你的主窗体(或其他任何东西)可以实现 IObserver

      【讨论】:

        【解决方案4】:

        你可以很容易地使用事件来实现它。我正在提供示例代码 -

        public class MyForm : Form
        {
            public event Action btn1Clicked;
            private void button1_Click(object sender, EventArgs e)
            {
                btn1Clicked();
            }
        }
        
        public abstract class AbsObserver
        {
            protected MyForm Form;
            public AbsObserver(Subject subject)
            {
                subject.Attach(OnNotify);
                Form = new MyForm();
                Form.btn1Clicked += Form_btn1Clicked;
            }
        
            void Form_btn1Clicked()
            {
                Console.WriteLine("Do button click task");
            }
        
            public abstract void OnNotify();
        }
        
        public class Observer1 : AbsObserver
        {
            public Observer1(Subject subject)
                : base(subject)
            {
            }
        
            public override void OnNotify()
            {
                Console.WriteLine("observer1 notified");
            }
        }
        public class Observer2 : AbsObserver
        {
            public Observer2(Subject subject)
                : base(subject)
            {
            }
        
            public override void OnNotify()
            {
                Console.WriteLine("observer2 notified");
            }
        }
        public class Subject
        {
            private event Action Notify;
        
            public void Attach(Action a)
            {
                Notify += a;
            }
        
            private void NotifyAll()
            {
                Notify();
            }
        }
        

        这里的表单不是观察者。观察者有表单的对象,所有与表单相关的问题都由观察者处理。这是一种堆肥。

        【讨论】:

          猜你喜欢
          • 2016-02-20
          • 2023-04-10
          • 1970-01-01
          • 1970-01-01
          • 2021-11-22
          • 1970-01-01
          • 2013-12-30
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多