c#设计模式(3)—— 利用观察者模式模拟推送消息

1、观察者模式概念

  观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己的行为。

  观察者模式实现了表示层和数据逻辑层的分离,并定义了稳定的更新消息传递机制,并抽象了更新接口,使得可以有各种各样不同的表示层,即观察者。

  观察者模式在被观察者和观察者之间建立了一个抽象的耦合,被观察者并不知道任何一个具体的观察者,只是保存着抽象观察者的列表,每个具体观察者都符合一个抽象观察者的接口。

2、业务场景

  模拟管理系统推送最新讯息给对应用户,采用观察者模式将很好的模拟此类场景,使发布者与订阅者之间实现解耦。

3、实战

3.1 定义实体对象

定义订阅者实体类

namespace SubscriberDesignWithRedis.Model
{
    public class User
    {
        /// <summary>
        /// 用户id
        /// </summary>
        public string userId { get; set; }
        /// <summary>
        /// 用户名称
        /// </summary>
        public string userName { get; set; }
    }
}

此处List<User> 用于存储订阅者列表

namespace SubscriberDesignWithRedis.Model
{
    [Serializable]
    public class Information
    {
        /// <summary>
        /// 发布者集合
        /// </summary>
        public List<User> userList{ get; set; }
        /// <summary>
        /// 信号
        /// </summary>
        public string signal { get; set; }
        /// <summary>
        /// 消息
        /// </summary>
        public string info { get; set; }
    }
}

3.2 发布者

    /// <summary>
    /// 门户发布信息
    /// </summary>
    public class PortalPublish
    {
        /// <summary>
        /// 定义委托方法,充当订阅者接口
        /// </summary>
        /// <param name="obj"></param>
        public delegate void NotifySubscribeEventHandler(object obj);

        /// <summary>
        /// 发布消息内部类
        /// </summary>
        public class PublishInfo
        {
            public NotifySubscribeEventHandler notifyEvent;
            /// <summary>
            /// 消息实体
            /// </summary>
            public Information Information { get; set; }
            /// <summary>
            /// 重载构造器
            /// </summary>
            /// <param name="information">消息实体</param>
            public PublishInfo(Information information)
            {
                this.Information = information;
            }
            /// <summary>
            /// 新增
            /// </summary>
            /// <param name="ob"></param>
            public void AddSubscribe(NotifySubscribeEventHandler ob){
                notifyEvent += ob;
            }
            /// <summary>
            /// 删除
            /// </summary>
            /// <param name="ob"></param>
            public void RemoveSubscribe(NotifySubscribeEventHandler ob){
                notifyEvent -= ob;
            }
            /// <summary>
            /// 更新( 使用lamda表达式 )
            /// </summary>
            public void Update() => notifyEvent?.Invoke(this);
        }
        public class PortalPublishInfo : PublishInfo
        {
            public PortalPublishInfo(Information information) : base(information) { }
        }
    }

3.3 订阅者

namespace SubscriberDesignWithRedis
{
    public class Subscriber
    {
        public string Name { get; set; }
        public Subscriber(string name)
        {
            this.Name = name;
        }
        /// <summary>
        /// 接收
        /// </summary>
        /// <param name="obj"></param>
        public void Recevie(object obj)
        {
            PortalPublish.PortalPublishInfo portalPublishInfo = obj as PortalPublish.PortalPublishInfo;
            if(portalPublishInfo != null)
            {
                Console.WriteLine("Notified {0} of {1}‘s " + "Info is :{2}", Name,             portalPublishInfo.Information.signal, portalPublishInfo.Information.info);
            }
        }
    }
}

3.4 测试类

namespace SubscriberDesignWithRedis
{
    class Program
    {
        static void Main(string[] args)
        {
            //模拟订阅者的集合
            List<User> userList = new List<User>() {
                new User() { userId = "1", userName = "ozil" },
                new User() { userId = "2",userName = "Alexis"}
            };
            //定义发布数据
            Information information = new Information() {
                signal = "Publish Info",
                info = "this is a new information for each client",
                userList = userList
            };
            PortalPublishInfo portalPublish = new PortalPublishInfo(information);
            Console.WriteLine("添加订阅者");
            //循环订阅者列表,将消息发送给具体订阅者
            foreach (User user in userList)
            {
                Subscriber client = new Subscriber(user.userName);
                portalPublish.AddSubscribe(new NotifySubscribeEventHandler(client.Recevie));
            }
            //执行事件
            portalPublish.Update();
            Console.WriteLine("--------------------------------------------");

            Console.WriteLine("移除订阅者");
            foreach (User user in userList)
            {
                Subscriber client = new Subscriber(user.userName);
                portalPublish.RemoveSubscribe(new NotifySubscribeEventHandler(client.Recevie));
            }
            //执行事件
            portalPublish.Update();
            Console.ReadLine();
        }
    }
}

4、运行结果

时间: 2024-08-06 15:27:07

c#设计模式(3)—— 利用观察者模式模拟推送消息的相关文章

java-给微信推送消息 利用企业微信

目的:给关注用户推送消息 场景:自动化测试,运维监控,接口访问等报错预警.例如线上接口报错,发送提醒消息 准备工作: 1:注册企业号(为什么不用公众号呢?) 企业号注册 2:常用参数介绍: 1:CORPID 企业号唯一标志符号. 位置:点击首页企业名称,企业资料中有key:CorpID 2:CORPSECRET: 需要创建单独等应用.具体步骤,按照提示一步一步来即可.需关注2个参数 Secret 和 AgentId(用于区分给哪个应用推送消息) 3:发送消息准备工作: 关注自己的企业号.(需要先

微信公众平台向特定用户推送消息

最近研究微信公众平台,这里整理了一下向特定用户推送消息的思路 一.首先需要将微信的openid与系统用户绑定. 在用户关注公众平台的时候,回复一个链接,要求用户绑定,可以设计如下消息进行回复,(openid最好进行加密处理,后者还需要用这个字段绑定fakeid). 欢迎关注有问必答平台,<a href='http://myweixin123.duapp.com/[email protected]'>点击此处进行用户绑定</a>! 在bind.html页面将openid与系统的use

signalr推送消息

参考:Tutorial: Getting Started with SignalR 2 and MVC 5 环境:vs2013,webapi2,entity framework6.0 实现效果:当用户上传一个文件时候,推送消息给关注此用户的其他用户,告知此用户上传了一个新的文件. 推送原理:当前端用户打开网页时候,SignalR 服务端会自动生成一个guid类型的ConnectionId.此ConnectionId用来连接确定用户端,用来确定发送给哪个当前在线用户.当要推送消息时候,后端方法会根

百度云推送消息到达率低问题定位分析

去年做我们这个产品的时候,SE在客户端设计了一个推送功能,SE经过调研决定在Android和IOS端都集成百度的云推送SDK来支持这个推送功能.最近领导在做运营分析的时候,发现云推送的报表显示,在Android端消息的达到率非常低,设备的在线率波动比较大,有时高有时非常低. 我们的这个产品经过将近两年的折腾进步是有目共睹的,在今年的巴塞罗那GSMA世界移动通信大会上荣获"Best Mobile Music App"大奖,让我们这帮苦逼了将近两年的屌丝士气大振,领导也欣喜不已并且决定将精

DWR3实现服务器端向客户端精确推送消息

原贴地址:http://blog.csdn.net/luojia_wang/article/details/8825929 研究了一天半,终于模拟出了这个功能,网上DWR的资料不少,但是真正实现客户端向服务器端精确推送消息的只有两篇文章.但是代码都只有一部分,向我这种刚开始学习DWR的人来说要看懂真的蛮难.不过即便如此,http://www.blogjava.net/stevenjohn/archive/2012/07/07/382447.html这片文章还是给了我很大帮助,再次表示感谢,下面我

(转)移动端主动推送消息原理

转:https://www.zhihu.com/question/19628406/answer/77205019 一.服务端主动推送消息到客户端过程 作者:谢泽帆   李琰链接:https://www.zhihu.com/question/24938934/answer/85359794来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 服务端主动推送到客户端是怎么一个过程 目前服务端给客户端推送,普遍做法是客户端与服务端维持一个长连接,客户端定时向服务端发送心跳以

实现友盟推送消息的完全自定义处理

1,下面的前提是必须申请了友盟且有app key 2,集成友盟SDK  参看官方文档http://dev.umeng.com/push/android/integration#1 3,若开发者需要实现对消息的完全自定义处理,则可以继承 UmengBaseIntentService, 实现自己的Service来完全控制达到消息的处理.     1,实现一个类,继承 UmengBaseIntentService, 重写onMessage(Context context, Intent intent)

DWR实现服务器向客户端推送消息

原文链接 http://www.blogjava.net/stevenjohn/archive/2012/07/07/382447.html这片文章还是给了我很大帮助,再次表示感谢,下面我将这两天的研究详细记录下来备忘,也希望能帮助到像我一样的人.只写过程,不写原理(不是不写,而是有些地方我也不太懂),下面开始: 第一.在项目中引入dwr.jar,然后在web.xml中进行配置,配置如下: <servlet> <servlet-name>dwr-invoker</servle

点击推送消息跳转处理(iOS)

当用户点击收到的推送消息时候,我希望打开APP,并且跳转到对应的界面,这就需要在AppDelegate里面对代理方法进行处理. 当用户点击推送消息打开APP的时候会调用 - (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions launchOptions中会有推送消息的userInfo信息,此时我们可以通过 NSDictionary* rem