大话设计模式:观察者模式

一、什么是观察者模式
一对多的依赖关系,多个观察者同时监听一个通知者

当一个对象被修改时,通知它的依赖对象,使得它们能够自己更新自己。也就是说大家都很关心一件事,当这件事发生的时候自己要办点啥事。其实项目中哪些对象关心啥是不清楚的,应该倒过来考虑,有一个事件是可能许多对象都要监测的,那这个事件就是大家关心的事件,谁要关心,就把谁关联上。

UML图

在这里插入图片描述

Subject:通知者抽象类,负责添加和删除被通知的对象以及通知信息.它是关联观察者的。
ConcreteSubject:具体的通知者,继承通知者抽象类,有具体的通知信息。
Observer:观察者抽象类,有一个随通知信息来而做的反应.
ConcreteObserver: 具体的观察者,更多的是依赖于抽象

二、适用场景

一个变化下随之会有许多其他变化,引发变化者不必知道都有哪些跟随者,众多跟随者也不必知道其它跟随者的存在,我就做我自己的。一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。比如微博以为流量明星发布一条动态,所有粉丝就会收到这个通知,粉丝之间不需知道对方的存在。明星也不需要真的知道都有哪些粉丝,他做的是无差别发布信息。

三、优缺点

优点
依赖于抽象不依赖与具体,抽象耦合
一套触发机制,依赖的是接口而不是具体对象。

缺点
通知者如果有很多观察者,将所有的观察者通知到位会花费很多时间
观察者模式只是让通知者将信息告知观察者,但没有机制能知道观察者都是如何反应的。

四、大话中的例子

公司员工上班看股票:每当老板回来童子哲就通知同事“老板回来了”,然后同事们就收起看股票的网页。建一个通知者的类,让前台和老板都继承这个类,都具备通知的功能, 同事们也有一个抽象父类里面有一个 方法用于反应通知者发来的信息,同事们具体实现这个反应方法的内容不一样。将需要接受信息的同事注册到或者说是添加到通知者类里面,通知者类一个方法统一调用这些注册的同事的反应方法。

五、我的例子

传统的观察者模式

using System;
using System.Collections.Generic;


namespace ObserverMode
{
    class Program
    {
        static void Main(string[] args)
        {

            Naruto naruto = new Naruto();//鸣人,通知者
            FoxCoat zilaiye = new FireNinja(naruto, "自来也");//观察者
            FoxCoat xiaoyin = new WaterNinja(naruto, "小樱");//观察者
            Console.WriteLine("==================第一波进攻=============");
            naruto.Add(new SoilNinja(naruto, "大野木"));//观察者注册
            naruto.Add(zilaiye);
            naruto.Add(new WaterNinja(naruto, "纲手"));
            naruto.Add(xiaoyin);
            naruto.info = "宇智波.斑攻过来了!";
            naruto.Notify();
            Console.WriteLine("自来也阵亡");
            Console.WriteLine("小樱阵亡");
            Console.WriteLine("==================第二波进攻=============");
            naruto.Remove(zilaiye);//观察者取消注册
            naruto.Remove(xiaoyin);//观察者取消注册
            naruto.Notify();
            Console.ReadKey();
        }
    }

    /// <summary>
    /// 妖狐外衣,可以接收妖狐之力使用者传来的信息并做出行动
    /// </summary>
    public abstract class FoxCoat
    {
        FoxStrength _foxStrength;//妖狐之力
        public FoxStrength @FoxStrength { get => _foxStrength; }
        public FoxCoat(FoxStrength foxStrength)//不需要妖狐之力信息得情况下,其实可以不必要持有妖狐之力的对象
        {
            _foxStrength = foxStrength;
        }
        public abstract void Update();
    }


    /// <summary>
    /// 妖狐之力
    /// </summary>
    public abstract class FoxStrength
    {
        List<FoxCoat> foxCoats = new List<FoxCoat>();//关联所有妖狐外衣使用者
        public string info;
        public void Add(FoxCoat foxCoat)
        {
            foxCoats.Add(foxCoat);
        }

        public void Remove(FoxCoat foxCoat)
        {
            foxCoats.Remove(foxCoat);
        }

        public void Notify()
        {
            foreach (FoxCoat item in foxCoats)
            {
                item.Update();//通知所有妖狐外衣使用者做出行动
            }
        }
    }

    public class Naruto : FoxStrength//依赖于抽象,而不依赖于具体
    {
        public void Skill()
        {
            Console.WriteLine("鸣人的技能");
        }
    }

    /// <summary>
    /// 土系忍者
    /// </summary>
    public class SoilNinja : FoxCoat
    {
        string name;
        public SoilNinja(FoxStrength foxStrength, string name) : base(foxStrength)
        {
            this.name = name;
        }

        public override void Update()
        {
            Console.WriteLine("{0} {1}发动忍术 土遁.土流城壁", FoxStrength.info, name);
        }
    }

    /// <summary>
    /// 火系忍者
    /// </summary>
    public class FireNinja : FoxCoat
    {
        string name;
        public FireNinja(FoxStrength foxStrength, string name) : base(foxStrength)
        {
            this.name = name;
        }

        public override void Update()
        {
            Console.WriteLine("{0} {1}发动忍术 火遁.蛤蟆油炎弹", FoxStrength.info, name);
        }
    }

    /// <summary>
    /// 水系忍者
    /// </summary>
    public class WaterNinja : FoxCoat
    {
        string name;
        public WaterNinja(FoxStrength foxStrength, string name) : base(foxStrength)
        {
            this.name = name;
        }

        public override void Update()
        {
            Console.WriteLine("{0} {1}发动忍术 水遁.治疗术", FoxStrength.info, name);
        }
    }
}

运行结果

在这里插入图片描述

使用委托的观察者模式

class Program
    {
       static void Main(string[] args)
        {
         
            NarutoAndHinata narutoAndHinata = new NarutoAndHinata();
            ALeUncle yilei = new ALeUncle("一乐大叔");
            Sasuke zuozhu = new Sasuke("佐助");
            Loklee loklee = new Loklee("小李");
            Iluka iluka = new Iluka("伊鲁卡");
            narutoAndHinata.Married += iluka.Servefather;
            narutoAndHinata.Married += yilei.SendDiscount;
            narutoAndHinata.Married += loklee.SendTightFitting;
            narutoAndHinata.Married += zuozhu.SendCharacter;

            narutoAndHinata.MarriedCeremony();
            Console.ReadKey();
        }

 }
    //委托
    public delegate void EventHandler();

    /// <summary>
    /// 鸣人和雏田
    /// </summary>
    public class NarutoAndHinata
    {
        public event EventHandler Married;//结婚事件


        /// <summary>
        /// 鸣人和雏田要结婚了
        /// </summary>
        public void MarriedCeremony()
        {
            Console.WriteLine("鸣人和雏田结婚了~");
            Married();
        }
    }

    /// <summary>
    /// 木叶人
    /// </summary>
    public abstract class Konoha
    {
        protected string name;
        public Konoha(string name)
        {
            this.name = name;
        }

    }

    /// <summary>
    /// 伊鲁卡
    /// </summary>
    public class Iluka : Konoha
    {
        public Iluka(string name) : base(name)
        {
        }

        public void Servefather()
        {
            Console.WriteLine("{0}:“我来当你爸。”", name);
        }
    }

    /// <summary>
    /// 洛克李
    /// </summary>
    public class Loklee : Konoha
    {
        public Loklee(string name) : base(name)
        {
        }

        public void SendTightFitting()
        {
            Console.WriteLine("{0}:“送你们一对哑铃。”", name);
        }
    }

    /// <summary>
    /// 一乐大叔
    /// </summary>
    public class ALeUncle : Konoha
    {
        public ALeUncle(string name) : base(name)
        {
        }

        public void SendDiscount()
        {
            Console.WriteLine("{0}:“送鸣人终身拉面免费券!”", name);
        }
    }

    /// <summary>
    /// 佐助
    /// </summary>
    public class Sasuke : Konoha
    {
        public Sasuke(string name) : base(name)
        {
        }

        public void SendCharacter()
        {
            Console.WriteLine("{0}飞鸽传书=>“寿”", name);
        }
    }
 运行结果

在这里插入图片描述

PS:在 未使用委托的情况下,注册的方法名需要一样,有了委托就没有这个限制,只需要具有相同的参数和返回值。这里的委托可以看做是对函数的抽象。 委托模式是对观察者模式进一步的抽象。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值