C#的观察者模式


前言

发布者(Publisher)= 被观察者(Observable) = 事件源(C#中的sender)
订阅者(Subscriber)=观察者(Observer)= 接收者(C#委托机制,直接按EventHandler实现回调方法)—>来源于DotNet工控上位机编程 公众号


一、EventHandler 是什么?

EventHandler 为 C# 中的预定义委托,专用于表示不生成数据的事件的事件的处理程序方法。
public delegate void EventHandler(Object sender, EventArgs e)–>来源于DotNet工控上位机编程 公众号

二、应用场景

1.使用方面

1.当一个抽象模型有两个方面,其中一个方面依赖于另一个方面,将这两者封装在独立的对象中以使它们可以各自独立地改变和复用的情况下。
2.当对一个对象的改变需要同时改变其他对象,而又不知道具体有多少对象有待改变的情况下。
3.当一个对象必须通知其他对象,而又不能假定其他对象是谁的情况下。

2.使用的优点

1.各个观察者或不干扰,只需要实现本身(观察者)的功能。
2.可随时进行绑定和解绑是否需要接受发布的通知。

三.使用说明Demo

1.Subject类

    /// <summary>
    /// Subject只是用于发布作用的类,类中包含将订阅的类加入集合函数AttachObserver,包含解除订阅的函数RemoveObserver,最主要是包含了发布通知函数NotifyAllObserver
    /// </summary>
    public class Subject
    {
        //将所有观察者放入list集合
        private List<Observer> observers = new List<Observer>();
      
        public void NotifyAllObserver()
        {
            foreach (Observer item in observers)
            {
                //调用观察者自身的更新函数即可
                item.Update();
            }
        }
        /// <summary>
        /// 加入集合
        /// </summary>
        /// <param name="observer"></param>
        public void AttachObserver(Observer observer)
        {
            observers.Add(observer);
        }
        /// <summary>
        /// 从观察者列表中去除
        /// </summary>
        /// <param name="observer"></param>
        public void RemoveObserver(Observer observer)
        {
            observers.Remove(observer);
        }
    }

2.Observer观察者抽象类

    /// <summary>
    /// 观察者抽象类
    /// </summary>
    public abstract class Observer
    {
        protected Subject subject;
        public abstract void Update();//抽象类中的函数只是写个名称,具体实现需要继承的子类中进行
    }

3.具体观察者,需要继承Observer基类,并且实现Update更新

public class Observer_A : Observer
    {
        public Observer_A(Subject subject)
        {
            this.subject = subject;
            this.subject.AttachObserver(this);//绑定Observer_A订阅者
        }
        //实现抽象类的方法,不开放出去
        public override void Update()
        {
            //这里编写Observer_A类中具体要实现的内容
        }
    }

    public class Observer_B : Observer
    {
        public Observer_B(Subject subject)
        {
            this.subject = subject;
            this.subject.AttachObserver(this);//绑定Observer_B订阅者
        }
        public override void Update()
        {
           //这里编写Observer_A类中具体要实现的内容
        }
    }

四.调用

		Subject obj_subject = new Subject();
        new Observer_A(obj_subject);
        new Observer_B(obj_subject);
        obj_subject.NotifyAllObserver();

使用事件也是同样道理。以下代码来源于DotNet工控上位机编程 公众号,作者DotNet天天编程

// 自定义一个事件类来保存事件信息
  public class CustomEventArgs : EventArgs
  {
      public CustomEventArgs(string s)
      {
          message = s;
      }
      private string message;
      public string Message
      {
          get { return message; }
          set { message = value; }
      }
   }
    // 广播事件的类
    class Publisher
    {
        // 使用 EventHandler<T> 声明一个事件
        public event EventHandler<CustomEventArgs> RaiseCustomEvent;
        //这个方法是做了一些事情。然后触发一个事件。
        public void DoSomething()
        {
            //DoSomething…………
            // 你也可以再触发事件前,执行一些其他的代码
            OnRaiseCustomEvent(new CustomEventArgs("Did something,hi 这是事件消息"));
        }
        //使用虚方法,让子类可以重写。to allow derived classes to override the event invocation behavior
        protected virtual void OnRaiseCustomEvent(CustomEventArgs e)
        {
            // 定义一个局部变量,已防止最后一个订阅者刚好在检查null后取消订阅
            EventHandler<CustomEventArgs> handler = RaiseCustomEvent;
            // 如果没有 订阅者(观察者), 委托对象将为null
            if (handler != null)
            {
                // 格式化事件消息中 的字符串
                e.Message += String.Format(" at {0}", DateTime.Now.ToString());
                // 这是最重要的一句。
                // 此时执行的  handler已经是一个多播委托(如果有多个订阅者或观察者注册)。
                // 既然是多播委托,就可以依次调用各个 回调函数 (既然是回调函数,实际的执行就由订阅者类决定)。
                //这里面传入一个this, 就代表 事件源(或发布者 或 被观察者 都一个意思)
                handler(this, e);
            }
        }
    }
    //用来注册事件的类
    class Subscriber
    {
        private string id;
        public Subscriber(string ID, Publisher pub)
        {
            id = ID;//注册这个动作,应该有订阅者主动进行,并且可以再后期取消注册
            pub.RaiseCustomEvent += HandleCustomEvent;
        }
        // 实现回调函数。在事件发生后,执行什么样的操作。这里只是简单的打印信息。
        void HandleCustomEvent(object sender, CustomEventArgs e)
        {
            //这就是实际的操作。
            Console.WriteLine(id + " received this message: {0}", e.Message);
        }
    }
    class Class1
    {
        static void Main(string[] args)
        {
            Publisher pub = new Publisher();
            Subscriber sub1 = new Subscriber("sub1", pub);
            Subscriber sub2 = new Subscriber("sub2", pub);
            // 调用这个方法来产生事件
            pub.DoSomething();
            Console.WriteLine("Press Enter to close this window.");
            Console.ReadLine();
        }
    }
  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个 C#观察者模式实例: ```csharp using System; using System.Collections.Generic; // 被观察者接口 interface ISubject { void Attach(IObserver observer); // 添加观察者 void Detach(IObserver observer); // 移除观察者 void Notify(); // 通知观察者 } // 观察者接口 interface IObserver { void Update(ISubject subject); // 接收通知并更新 } // 具体的被观察者类 class ConcreteSubject : ISubject { private List<IObserver> observers = new List<IObserver>(); private string state; // 被观察者状态 // 添加观察者 public void Attach(IObserver observer) { observers.Add(observer); } // 移除观察者 public void Detach(IObserver observer) { observers.Remove(observer); } // 通知观察者 public void Notify() { foreach (IObserver observer in observers) { observer.Update(this); } } // 修改状态并通知观察者 public void SetState(string state) { this.state = state; Notify(); } public string GetState() { return state; } } // 具体的观察者类 class ConcreteObserver : IObserver { private string name; // 观察者名称 public ConcreteObserver(string name) { this.name = name; } // 接收通知并更新 public void Update(ISubject subject) { Console.WriteLine("{0} 接收到了被观察者的通知,当前状态为 {1}", name, ((ConcreteSubject)subject).GetState()); } } // 测试代码 class Program { static void Main(string[] args) { ConcreteSubject subject = new ConcreteSubject(); // 添加观察者 subject.Attach(new ConcreteObserver("观察者 A")); subject.Attach(new ConcreteObserver("观察者 B")); subject.Attach(new ConcreteObserver("观察者 C")); // 修改状态并通知观察者 subject.SetState("状态 1"); // 移除观察者 subject.Detach(new ConcreteObserver("观察者 B")); // 修改状态并通知观察者 subject.SetState("状态 2"); Console.ReadKey(); } } ``` 以上代码实现了一个简单的观察者模式实例,其中 `ConcreteSubject` 是具体的被观察者类,实现了 `ISubject` 接口;`ConcreteObserver` 是具体的观察者类,实现了 `IObserver` 接口。在测试代码中,我们创建了一个 `ConcreteSubject` 对象,并添加了三个观察者,然后修改了状态并通知观察者,最后移除了一个观察者并再次修改状态并通知观察者。运行该程序,控制台输出如下: ``` 观察者 A 接收到了被观察者的通知,当前状态为 状态 1 观察者 B 接收到了被观察者的通知,当前状态为 状态 1 观察者 C 接收到了被观察者的通知,当前状态为 状态 1 观察者 A 接收到了被观察者的通知,当前状态为 状态 2 观察者 C 接收到了被观察者的通知,当前状态为 状态 2 ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值