• 个人对“观察者模式”的一些整理


    在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系” ——一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知。如果这样的依赖关系过于紧密,将使软件不能很好地抵御变化。使用面向对象技术,可以将这种依赖关系弱化,并形成一种稳定的依赖关系。从而实现软件体系结构的松耦合。

    定义:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新

    生活场景: 假设有个超女,有很多粉丝追求她,每次开发布会,说:“姐来了,快出来给我投票啊!我要发行新专辑了,要签名的都过来啊”;结果,一群粉丝都蜂拥而上,找她签名,满足追星的愿望。这样就形成了:超女——粉丝,关注和被关注的关系,在软件方面可以归为:观察者模式

    终极目标:实现 召开招聘会就发消息给粉丝们。

    第一种思路:我这水平的人的普遍想法

    代码
     class Program
        {
            
    static void Main(string[] args)
            {
                Girl qqGril
    =new Girl();
                Boy haha1 
    = new Boy("haha", qqGril);
                 qqGril.Addboys(haha1);
                 qqGril.SetMsg 
    = "我要开发布会啦,想找我签名的快死过来!";
                 qqGril.SendMsg();
                Console.ReadLine();
            }
        }
        
    class Girl
        {
            List
    <Boy> boyLs = new List<Boy>();//泛型集合 装载 粉丝门
            public void Addboys(Boy sx)
            {
    //添加一个粉丝
                boyLs.Add(sx);
            }
            
    public void Removeboys(Boy sx)
            {
    //看这家伙不爽 ,删除掉
                boyLs.Remove(sx);
            }
            
    public void SendMsg()
            {
    //开发布会给粉丝们发消息
                foreach (Boy b in boyLs)
                {
                    b.ShowMsg();
                }
            }
            
    /// <summary>
            
    /// 设置发送信息
            
    /// </summary>
            private string _SetMsg;
            
    public string SetMsg
            {
                
    get { return _SetMsg; }
                
    set { _SetMsg = value; }
            }
        }
        
    class Boy
        {
            
    private string name;
            
    private Girl girl;
            
    public Boy(string name, Girl girl)
            {
                
    this.name = name;
                
    this.girl = girl;
            }
            
    public void ShowMsg()
            {
                Console.WriteLine(
    "美女发消息给:{0},{1}", name, girl.SetMsg);
            }
        }

    运行结果

     这样写不好的地方是耦合度太高,如果要发消息给电视台 还要在增加一个电视台的类,这样就需要提取重构

    代码
    class Program
        {
            
    static void Main(string[] args)
            {
                Girl qqGril
    =new Girl();
                Boy haha1 
    = new Boy("haha", qqGril);
                CCTV cctv 
    = new CCTV("电视台", qqGril);
                 qqGril.Addboys(haha1);
                 qqGril.Addboys(cctv);
                 qqGril.SetMsg 
    = "我要开发布会啦";
                 qqGril.SendMsg();
                Console.ReadLine();
            }
        }
        
    class Girl
        {
            List
    <Observer> boyLs = new List<Observer>();//泛型集合 装载 粉丝门
            public void Addboys(Observer sx)
            {
    //添加一个粉丝
                boyLs.Add(sx);
            }
            
    public void Removeboys(Observer sx)
            {
    //看这家伙不爽 ,删除掉
                boyLs.Remove(sx);
            }
            
    public void SendMsg()
            {
    //开发布会给粉丝们发消息
                foreach (Observer b in boyLs)
                {
                    b.ShowMsg();
                }
            }
            
    /// <summary>
            
    /// 设置发送信息
            
    /// </summary>
            private string _SetMsg;
            
    public string SetMsg
            {
                
    get { return _SetMsg; }
                
    set { _SetMsg = value; }
            }
        }
        
    /// <summary>
        
    /// 观察者基类
        
    /// </summary>
        abstract class Observer
        {
            
    protected string name;
            
    protected Girl girl;
            
    public Observer(string name, Girl girl)
            {
                
    this.name = name;
                
    this.girl = girl;
            }
            
    public abstract void ShowMsg();//虚方法
        }
        
    class Boy:Observer
        {
            
    public Boy(string name, Girl girl)
                : 
    base(name, girl)
            { }
            
    public override void ShowMsg()
            {
                Console.WriteLine(
    "美女发消息给:{0},{1},快来要签名",name,girl.SetMsg);
            }
        }
        
    class CCTV : Observer
        {
            
    public CCTV(string name, Girl girl)
                : 
    base(name, girl)
            { }
            
    public override void ShowMsg()
            {
                Console.WriteLine(
    "美女发消息:{0},快来采访", girl.SetMsg);
            }
        }

    结果如下:

    但是只完成了一半,因为 超女毕竟也会老去,也不可能一直红下去,所以我们可能又去关注其它方面,比如,房价怎么还没降啊,物价又上涨了等等,这些都可以抽象为一个接口,然后让具体的被观察者去继承这个接口:

    代码
     class Program
        {
            
    static void Main(string[] args)
            {
                Subject qqGril 
    = new Girl();
                Boy haha1 
    = new Boy("haha", qqGril);
                CCTV cctv 
    = new CCTV("电视台", qqGril);
                 qqGril.Addboys(haha1);
                 qqGril.Addboys(cctv);
                 qqGril.SetMsg 
    = "我要开发布会啦";
                 qqGril.SendMsg();
                Console.ReadLine();
            }
        }
        
    interface Subject
        {
            
    void Addboys(Observer sx);
            
    void SendMsg();
            
    string SetMsg
            {
                
    get;
                
    set;
            }
        }
        
    class Girl : Subject
        {
            List
    <Observer> boyLs = new List<Observer>();//泛型集合 装载 粉丝门
            public void Addboys(Observer sx)
            {
    //添加一个粉丝
                boyLs.Add(sx);
            }
            
    public void Removeboys(Observer sx)
            {
    //看这家伙不爽 ,删除掉
                boyLs.Remove(sx);
            }
            
    public void SendMsg()
            {
    //开发布会给粉丝们发消息
                foreach (Observer b in boyLs)
                {
                    b.ShowMsg();
                }
            }
            
    /// <summary>
            
    /// 设置发送信息
            
    /// </summary>
            private string _SetMsg;
            
    public string SetMsg
            {
                
    get { return _SetMsg; }
                
    set { _SetMsg = value; }
            }
        }
        
    /// <summary>
        
    /// 观察者基类
        
    /// </summary>
        abstract class Observer
        {
            
    protected string name;
            
    protected Subject girl;
            
    public Observer(string name, Subject girl)
            {
                
    this.name = name;
                
    this.girl = girl;
            }
            
    public abstract void ShowMsg();//虚方法
        }
        
    class Boy:Observer
        {
            
    public Boy(string name, Subject girl)//这样的好处是:观察者观察的是 抽象的被观察着,这样就不局限在“超女”这一方面,可以是国家物价局,国家铁道部等等,只要实现了Subject接口
                : base(name, girl)
            { }
            
    public override void ShowMsg()
            {
                Console.WriteLine(
    "美女发消息给:{0},{1},快来要签名",name,girl.SetMsg);
            }
        }
        
    class CCTV : Observer
        {
            
    public CCTV(string name, Subject girl)
                : 
    base(name, girl)
            { }
            
    public override void ShowMsg()
            {
                Console.WriteLine(
    "美女发消息:{0},快来采访", girl.SetMsg);
            }
        }

     观察者模式:定义了一对多的关系,让多个观察者对象同时监听某一主题对象,这个主题对象在状态发生改变的时候就会通知所有观察对象,使他们能够自动更新自己。

    虽然上面的观察者和被观察者都被抽象出来,但是还有问题:抽象通知者还是依赖抽象观察者,如果没有抽象观察者这个接口,就没法完成通知任务,而且并不是每个具体的观察方法都有ShowMsg()这个方法,所以还是有不足之处

    委托和事件解决方法:

    代码
    class Program
        {
            
    static void Main(string[] args)
            {
                Girl qqGril 
    = new Girl();
                Boy haha1 
    = new Boy("haha", qqGril);
                CCTV cctv 
    = new CCTV("电视台", qqGril);
                qqGril.SendAllMsg 
    += new EventHander(haha1.ShowBoyMsg);
                qqGril.SendAllMsg 
    += new EventHander(cctv.ShowCCTVMsg);
                 qqGril.SendMsg();
                Console.ReadLine();
            }
        }
        
    interface Subject
        {
            
    //void Addboys(Observer sx);//抽象通知者由于不依赖抽象观察者,所以增加的方法也不要了
            void SendMsg();
            
    string SetMsg
            {
                
    get;
                
    set;
            }
        }
        
    delegate void EventHander();//声明一个无参数,无返回值的委托 EventHander
        class Girl : Subject
        {
            
    //List<Observer> boyLs = new List<Observer>();
            
    //public void Addboys(Observer sx)
            
    //{//添加一个粉丝
            
    //    boyLs.Add(sx);
            
    //}
            
    //public void Removeboys(Observer sx)
            
    //{//看这家伙不爽 ,删除掉
            
    //    boyLs.Remove(sx);
            
    //}
            
    //public void SendMsg()
            
    //{//开发布会给粉丝们发消息
            
    //    foreach (Observer b in boyLs)
            
    //    {
            
    //        b.ShowMsg();
            
    //    }
            
    //}
            public event EventHander SendAllMsg;//声明一个 委托为 eventHander的事件
            public void SendMsg()
            {
    //开发布会给粉丝们发消息
                if (SendAllMsg != null)
                    SendAllMsg();
            }
            
    /// <summary>
            
    /// 设置发送信息
            
    /// </summary>
            private string _SetMsg;
            
    public string SetMsg
            {
                
    get { return _SetMsg; }
                
    set { _SetMsg = value; }
            }
        }
        
    class Boy 
        {
            
    protected string name;
            
    protected Subject girl;
            
    public Boy(string name, Subject girl)
            {
                
    this.name = name;
                
    this.girl = girl;
            }
            
    public  void ShowBoyMsg()//修改方法名称为ShowBoyMsg
            {
                Console.WriteLine(
    "美女发消息给:{0},{1},快来要签名", name, girl.SetMsg);
            }
        }
        
    class CCTV 
        {
            
    protected string name;
            
    protected Subject girl;
            
    public CCTV(string name, Subject girl)
            {
                
    this.name = name;
                
    this.girl = girl;
            }
            
    public  void ShowCCTVMsg()////修改方法名称为ShowCCTVMsg
            {
                Console.WriteLine(
    "美女发消息:{0},快来采访", girl.SetMsg);
            }
        }

     这是在看完《大话设计模式》这本书后,根据里面的内容自己小结的,当然更具体的介绍还要去仔细阅读那本书,

     《大话设计模式》这本书真的很不错,特别推荐。当然自己也是菜鸟,今天工作不忙就整理了,也希望能提高自己

  • 相关阅读:
    1 外部JavaScript
    1 外部JavaScript
    蓝桥杯:位运算
    Java为什么要配置环境变量
    java数组静态复制和动态复制越界问题
    Dijkstra算法java实现
    离散二元关系实验java实现
    Java中字符串split() 的使用方法
    用java编程实现集合的交、并、差和补运算
    61根据字符出现频率排序(451)
  • 原文地址:https://www.cnblogs.com/6303c/p/1892242.html
Copyright © 2020-2023  润新知