请选择 进入手机版 | 继续访问电脑版

马上加入IBC程序猿 各种源码随意下,各种教程随便看! 注册 每日签到 加入编程讨论群

C#教程 ASP.NET教程 C#视频教程程序源码享受不尽 C#技术求助 ASP.NET技术求助

【源码下载】 社群合作 申请版主 程序开发 【远程协助】 每天乐一乐 每日签到 【承接外包项目】 面试-葵花宝典下载

官方一群:

官方二群:

观察者(Observer)模式———推

  [复制链接]
查看3599 | 回复8 | 2021-3-5 16:41:28 | 显示全部楼层 |阅读模式
本帖最后由 剑弑 于 2021-3-6 20:51 编辑

      首先在开始讲观察者模式之前我们先来看看现在很火自媒体软件是怎么工作的。做过自媒体的应该知道,我们要把自己精心录制的视频上传到自媒体平台,平台就会把我们的视频推送给关注我们的粉丝用户,让关注我们的粉丝用户可以第一时间享受到视频给他带来的精彩内容,而哪天粉丝用户对作者的视频不在喜欢了,取关了,平台也将不会在给些用户推送我们的视频了;当然自媒体平台不只有这功能,我们只是拿其中的一点来讲我们的观察者模式。
      从上面的示例中,我们能发现分别有作者、平台、粉丝用户三种角色,其中作者中平台是1对1的关系,而且平台跟粉丝用户是1对多的关系,作者不跟粉丝有直接接触的机会(当然线下会面不是我们考虑的范畴);我们把这三种角色实现在我们的对象,毕竟万物皆对象吗,相信这难不到我们,这个实现先留给大家去思考先(可以带前问题跟下面的类图一起思考,来设计我们观察者模式)。
接下来我们先来看看观察者模式的类图:
ClassDiagram1.png
从类图我们可以看出有两个接口,分别是Subject和UserObserver,其他的类都只是这两个接口类的实现(注:两接口间的连线在vs类图中是不应该存在的,这里只是为了更好表明关系)。
我们来看看具体的代码实现,如下:
Subject
[C#] 纯文本查看 复制代码
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Observer
{
    interface Subject
    {

        /// <summary>
        /// 注册观察者
        /// </summary>
        /// <param name="observer"></param>
        void RegisterObserver(UserObserver observer);

        /// <summary>
        /// 移除观察者(取消注册)
        /// </summary>
        /// <param name="observer"></param>
        void RemoveObserver(UserObserver observer);

        /// <summary>
        /// 发布通知
        /// </summary>
        /// <param name="observer"></param>
        void ReleaseObserver();
    }
}

UserObserver
[C#] 纯文本查看 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Observer
{
    interface UserObserver
    {
        void Release(string byteContent,DateTime releaseDatetime,string name);
    } 
}

SelfMediaSubject
[C#] 纯文本查看 复制代码
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Observer
{
    class SelfMediaSubject : Subject
    {
        private List<UserObserver> listObserver;

        #region 可整合成实体
        /// <summary>
        /// 视频内容
        /// </summary>
        private string byteContent;
        /// <summary>
        /// 视频发布时间
        /// </summary>
        private DateTime releaseDatetime;
        /// <summary>
        /// 视频名称
        /// </summary>
        private string name;
        #endregion


        public SelfMediaSubject()
        {
            listObserver = new List<UserObserver>();
        }

        /// <summary>
        /// 注册观察者
        /// </summary>
        /// <param name="observer"></param>
        public void RegisterObserver(UserObserver observer)
        {
            listObserver.Add(observer);
        }

        /// <summary>
        /// 主题发布通知
        /// </summary>
        /// <param name="observer"></param>
        public void ReleaseObserver()
        {
            foreach (var observer in listObserver)
            {
                observer.Release(byteContent,releaseDatetime,name);
            }
        }

        /// <summary>
        /// 移除观察者
        /// </summary>
        /// <param name="observer"></param>
        public void RemoveObserver(UserObserver observer)
        {
            if (listObserver.IndexOf(observer) >= 0)
                listObserver.Remove(observer);
        }

        /// <summary>
        /// 作者发布视频
        /// </summary>
        public void ReleaseVideo()
        {
            ReleaseObserver();
        }

        /// <summary>
        /// 主题数据更改
        /// </summary>
        /// <param name="byteContent"></param>
        /// <param name="releaseDatetime"></param>
        /// <param name="name"></param>
        public void setVideo(string byteContent, DateTime releaseDatetime, string name)
        {
            this.byteContent = byteContent;
            this.releaseDatetime = releaseDatetime;
            this.name = name;
            ReleaseVideo();
        }
    }
}

LiUserObserver
[C#] 纯文本查看 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Observer
{
    class LiUserObserver : UserObserver
    {
        private Subject aSubject;

        #region 可整合成实体
        /// <summary>
        /// 视频内容
        /// </summary>
        private string byteContent;
        /// <summary>
        /// 视频发布时间
        /// </summary>
        private DateTime releaseDatetime;
        /// <summary>
        /// 视频名称
        /// </summary>
        private string name;
        #endregion

        public LiUserObserver(Subject subject)
        {
            aSubject = subject;
            aSubject.RegisterObserver(this);
        }

        public void Release(string byteContent, DateTime releaseDatetime, string name)
        {
            this.byteContent = byteContent;
            this.name = name;
            this.releaseDatetime = releaseDatetime;
            Console.WriteLine($"我是{typeof(LiUserObserver).Name}");
            Console.WriteLine($"视频名称:{name},视频发布时间:{releaseDatetime}");
            Console.WriteLine("======================= 华丽分割线 =================================");
        }
    }
}

其他几个类跟LiUserObserver大致相同,差别只是类名不同跟显示不同,有兴趣的朋友可以自行实现后面我也会把源码上传。测试代码
[C#] 纯文本查看 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Observer
{
    class Program
    {
        static void Main(string[] args)
        {
            SelfMediaSubject subject = new SelfMediaSubject();
            LiUserObserver liUserObserver = new LiUserObserver(subject);
            LiuUserObserver liuUserObserver = new LiuUserObserver(subject);
            LaiUserObserver laiUserObserver = new LaiUserObserver(subject);
            subject.setVideo("1111",DateTime.Now,"生活记录1");
            Console.WriteLine("移除liuUserObserver");
            subject.RemoveObserver(liuUserObserver);
            Console.WriteLine("****************** 华丽分割线 **********************");
            subject.setVideo("2222", DateTime.Now, "生活记录2");
            subject.setVideo("3333", DateTime.Now, "生活记录3");
            subject.setVideo("4444", DateTime.Now, "生活记录4");
            Console.ReadLine();
        }
    }
}

结果
2.png
通过上面的观察者模式的代码细心的朋友就会发现其实他们是可以跟上面讲解的示例的角色对应的上的;请大家认真的思考比对,把上面的类图跟示例角色做个关联吧,让他们找到自己的归属地吧!!!!============================================ 我是华丽的分割线 =============================================
============================================ 我是华丽的分割线 =============================================
============================================ 我是华丽的分割线 =============================================重要的事要说三遍!!!!!
结合上面的示例我们可以很清楚的了解到,作者对应SelfMediaSubject类,他们都是给其他对象发布东西;平台对应着Subject,他们都可以让用户关注(注册)跟取关(移除)及推送视频(发布通知);而用户们对应的是LiUserObserver类(这里是1个用户对应一个类),他们都是享受者。
到这里很多对观察者模式有所了解的朋友就会问,为什么我看到别人讲的观察者模式Subject都是抽象类而不是接口呢?是你讲错了吗?你也太不可信了。
这些朋友的疑问没错,确实是存在抽象类的观察者模式; 但我们学习要循序渐进,要先一步一步来。
观察者模式其实是存在推、拉两种类型实现的,而我们今天讲的是推,下一章我们会讲观察者模式的拉是怎么实现的;观察者模式的定义及优缺点也将在下一章来补充。



Observer.rar

40.85 KB, 阅读权限: 20, 下载次数: 0

ibcadmin | 2021-3-7 17:25:14 | 显示全部楼层
+111111
C#论坛 www.ibcibc.com IBC编程社区
C#
C#论坛
IBC编程社区
*滑块验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则