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、运行结果

 

posted @ 2017-11-21 21:33  cklovefan  阅读(1009)  评论(0编辑  收藏  举报