设计模式——观察者模式

一、定义

        观察者模式又称发布-订阅(Publish/Subscribe)模式,这个模式有两种角色被观察者观察者多个观察者可以订阅某一个被观察者。被观察者通过委托或事件机制,在执行发布方法后调用观察者的某些方法。

二、委托法实现

        委托是一种数据类型使用delegate关键字定义。可以认为委托是函数指针,将方法名赋值给委托,委托就能记录下方法的地址,执行委托能够间接地调用方法。

        举例:博主(blogger)具有发布文章的方法;粉丝(fans)具有订阅博主、阅读博主文章的方法。现实现博主发布文章后,该博主的粉丝立即阅读文章。以下使用C#代码实现观察者模式,博主是被观察者,博主的两个粉丝是观察者

namespace Observer
{
    internal class Program
    {
        //定义一个委托,委托名为DelegateInBlogger,该委托能接收 返回值为void,参数为string的方法
        public delegate void DelegateInBlogger(string articleName);

        public class Blogger
        {
            //博主的委托属性为静态的,保证后续多个粉丝访问的是同一个委托
            public static DelegateInBlogger delegateInBlogger = null;

            public void publish(string articleName)
            {
                Console.WriteLine("博主发表了"+articleName);

                //执行委托多播,以articleName为参数分别调用粉丝1和粉丝2的Read方法
                delegateInBlogger(articleName);
            }
        }

        public class Fans1
        {
            string name = "粉丝1";
           
            //粉丝1订阅博主
            public void Subscript()
            {
                //为博主的静态委托属性赋值,将方法名Read赋值给委托
                Blogger.delegateInBlogger = Read;
            }
            public void Read(string articleName) {
                Console.WriteLine(name+"观看了"+ articleName);
            }
        }

        public class Fans2
        {
            string name = "粉丝2";
            
            //粉丝2订阅博主
            public void Subscript()
            {
                //往博主的静态委托属性添加方法名
                Blogger.delegateInBlogger += Read;
            }
            public void Read(string articleName)
            {
                Console.WriteLine(name + "观看了" + articleName);
            }
        }

        static void Main(string[] args)
        {
            Fans1 fans1 = new Fans1();
            fans1.Subscript();

            Fans2 fans2 = new Fans2();
            fans2.Subscript();

            new Blogger().publish("作品");

        }
    }
}

输出结果如下:

三、委托的问题

粉丝1订阅博主的代码如下:委托的初始值是null,所以需要直接为委托赋值。

public void Subscript(){
    Blogger.delegateInBlogger = Read;
}

粉丝2订阅博主的代码如下:粉丝1订阅后委托值不再是null,直接使用 "=" 运算对委托赋值会导致原有的委托方法被覆盖;使用 "+=" 运算表示委托合并,不会覆盖原有的委托方法。

public void Subscript(){
    Blogger.delegateInBlogger += Read;
}

使用委托实现观察者模式时,由于委托赋初始值和委托合并写法不同,因此需要区分开写。

四、事件法实现

        事件是对委托的封装。事件的优点在于能防止外部直接赋值(事件类型不能使用 = 进行赋值),同时提供了添加(+=)和移除(-=)两个方法进行委托合并。使用事件实现观察者模式,初始赋值和后续合并写法相同,代码更加简洁。

namespace Observer_Event
{
    internal class Program
    {
        public delegate void DelegateInBlogger(string articleName);

        public class Blogger
        {
            //将委托定义为事件
            public static event DelegateInBlogger delegateInBlogger = null;
            public void publish(string articleName)
            {
                Console.WriteLine("博主发表了" + articleName);
                delegateInBlogger(articleName);
            }
        }
        public class Fans
        {
            string Name { get; set; }
            public Fans(string name) { 
                this.Name = name;
            }

            public void Subscript()
            {
                //不需要考虑赋初始值问题
                Blogger.delegateInBlogger += Read;
            }
            public void Read(string articleName)
            {
                Console.WriteLine(Name + "观看了" + articleName);
            }
        }
        static void Main(string[] args)
        {
            Fans fans1 = new Fans("粉丝1");
            fans1.Subscript();

            Fans fans2 = new Fans("粉丝2");
            fans2.Subscript();

            new Blogger().publish("作品");
        }
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值