从闹铃理解观察者模式-C#事件

为了按时完成某事,常常需要闹铃提醒我们当前时间。没有闹铃存在,为了能够准确把握时间,要求我们频繁去观察钟表,即便如此,也经常会错过时间。这里我们创造一个事件案例,实现时钟可以时刻提醒人当前时间。

在自定义事件时,我们需要明确谁是订阅者(subscriber),谁是发布者(publisher),谁是客户端(client)。在这个案例中,时钟可以发布时间,供人观察,因此他是发布者,在观察者设计模式中也被称为监视对象;而人就是订阅者,即监视者。这里的客户端是指触发事件的类,例如本案例中Program类Main函数。

自定义一个事件,需要为不同角色规划不同工作。例如

  • 发布者需要拥有事件触发方法OnEventName、以及一个事件
  • 订阅者需要拥有与事件参数、返回值类型匹配的事件处理程序
  • 客户端需要将订阅者事件处理程序注册到发布者定义的事件中,并触发OnEventName

注:注册过程不一定总是出现在客户端。

反之,如何解读一个事件,即判断每一部分的角色。

  • 定义事件触发方法OnEventName的是发布者。
  • 触发OnEventName的客户端。
  • 在事件注册过程中很容易判断订阅者,因为订阅者的事件处理程序总是需要被注册到事件中。

namespace EventExample
{
    //一、声明一个事件处理委托(委托对象名称以EventHandler结尾)
    public delegate void TimeChangedEventHandler(object obj, TimeEventArgs args);

    //二、在事件发送者中完成事件定义、事件触发方法编写
    class Clock
    {
        //定义一个"TimeChanged"事件,注意其前面有两个关键字"event"和"TimeChangedEventHandler"
        public event TimeChangedEventHandler? TimeChanged;
        public Clock()
        {

        }

        //事件触发函数,我们的目标是每秒钟触发一次TimeChanged事件
        public void GoTime()
        {
            DateTime init = DateTime.Now;
            int h1 = init.Hour;
            int m1 = init.Minute;
            int s1 = init.Second;
            while (true)
            {
                DateTime now = DateTime.Now;
                int h2 = now.Hour;
                int m2 = now.Minute;
                int s2 = now.Second;
                if (s2 != s1)
                {
                    h1 = h2;
                    m1 = m2;
                    s1 = s2;
                    //首先建立一个TimeEventArgs对象来保存相关参数,这里是时分秒
                    TimeEventArgs args = new TimeEventArgs(h2, m2, s2);
                    //注意这种写法,这一句是用来触发事件,事件不是类,所以不用使用"new"关键字,而且我们看到,这里TimeChanged的两个参数跟我们的委托(TimeChangedEventHandler)是一致的
                    //其中第一个参数是触发这个事件的对象,我们这里使用的是一个时钟实例(this)
                    if (this.TimeChanged != null)
                    {
                        this.TimeChanged(this, args);
                    }
                }
            }
        }
    }
    //三、观察者类,定义"委托"的方法也就是某事件发生后跟进的某些事件处理程序
    //也就是void KnowTime(object obj,TimeEventArgs args)
    //从这个方法的定义可以看到,我们只会关心返回类型和方法的参数,而方法名称则无所谓
    class HardWorker
    {
        public void KnowTime(object obj, TimeEventArgs args)
        {
            Console.WriteLine("现在时间:" + args.Hour + ":" + args.Minute + ":" + args.Second);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Clock clock = new Clock(); //实例化一个事件发送者-时钟            
            HardWorker worker1 = new HardWorker(); //实例化一个观察者类-打工人

            //四、将打工人的事件处理程序knowTime注册到钟表的事件中
            clock.TimeChanged += new TimeChangedEventHandler(worker1.KnowTime);
            //五、在客户端中触发事件
            clock.GoTime();
        }
    }

    //TimeEventArgs是我们自己定义的一个类,用于保存事件中的参数.这里我们分别保存时间的时分秒
    public class TimeEventArgs : EventArgs
    {
        private int hour;
        private int minute;
        private int second;
        public TimeEventArgs(int hour, int minute, int second)
        {
            this.hour = hour;
            this.minute = minute;
            this.second = second;
        }
        public int Hour
        {
            get
            {
                return this.hour;
            }
        }
        public int Minute
        {
            get
            {
                return this.minute;
            }
        }
        public int Second
        {
            get
            {
                return this.second;
            }
        }
    }

}

代码运行结果如下:

  • 11
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值