【设计模式-9】观察者模式

参与者:

Subject(抽象主题)把所有观察者对象的引导保存到一个聚集里,每个抽象主题里边可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。
ConcreteSubject(具体主题)实现抽象主题接口,当状态发生变化时,发送消息通知给聚集里观察者
Observer(抽象观察者)为所有具体观察者定义一个接口,在得到主题通知时,更新自己。一般由抽象类或接口实现
ConcreteObserver(具体观察者)实现抽象观察者的更新接口,以便自身状态符合具体主题的状态,做出相应的变化。

抽象来说,对象B关心对象A的状态变化,当对象A状态变化时,通知对象B,对象B做出相应的操作。现实中,很多观察者模式的体现,比如微信关注了一个公众账号,公众账号有新文章,会推送给订阅它的用户,或者加了某人好友,他发布朋友圈,系统就会推送给你,你会根据他发的朋友圈,做出评论,点赞等操作。

在下面的情况下可以考虑使用观察者模式:

  • 当一个抽象模型有两个方面,其中一个方面依赖于另一个方面,将这两者封装在独立的对象中以使它们可以各自独立地改变和复用的情况下。
  • 当对一个对象的改变需要同时改变其他对象,而又不知道具体有多少对象有待改变的情况下。
  • 当一个对象必须通知其他对象,而又不能假定其他对象是谁的情况下。

优缺点:

  • 聚耦合:观察者模式在被观察者和观察者之间建立了一个抽象的耦合,被观察者并不知道任何一个具体的观察者,只是保存着抽象观察者的列表,每个具体观察者都符合一个抽象观察者的接口。
  • 容易出现循环调用:如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃,在使用观察者模式应特别注意这点。
  • 如果一个被观察者有很多直接和间接的观察者时,将所有的观察者都通知到会花费很多时间。
//Observer(抽象观察者)
public abstract class Friend
{
    //点赞
    public abstract void GiveLike();
    //评论
    public abstract void Comment();
    //收到朋友圈信息
    public abstract void ReceiveInfo(string _friendName);
}

//ConcreteObserver(具体观察者)
public class YourSelfFriend:Friend
{
    public string m_userName{get;set;}

    public YourSelfFriend(string _userName)
    {
        m_userName = _userName;
    }

    public override void GiveLike()
    {
        Debug.Log(m_userName + "点了个赞");
    }
    public override void Comment()
    {
        Debug.Log(m_userName + "评论了你");
    }
    public override void ReceiveInfo(string _friendName)
    {
        Debug.Log(m_userName + "-收到朋友圈 来自:" + _friendName);
    }
}

//Subject(抽象主题)
public abstract class PengYouQuan
{
    public string m_userName{get;set;}

    public PengYouQuan(string _userName)
    {
        m_userName = _userName;
    }

    //朋友圈的好友(一群观察者)
    public List<Friend> m_friendList = new List<Friend>();

    //增加一个观察者 (增加一个看朋友圈的人)
    public void AddFriend(Friend _friend)
    {
        if(!m_friendList.Contains(_friend))
        {
            m_friendList.Add(_friend);
        }
    }

    //删除一个观察者 (删除一个朋友圈的人)
    public void DeleteFriend(Friend _friend)
    {
        if(m_friendList.Contains(_friend))
        {
            m_friendList.Remove(_friend);
        }
    }

    //发布一条朋友圈,推送给好友
    public void PushInfo()
    {
        for(int i = 0;i < m_friendList.Count;i++)
        {
            Friend tempFriend = m_friendList[i];
            tempFriend.ReceiveInfo(m_userName);
        }
    }
}

//ConcreteSubject(具体主题)
public class MyselfPengYouQuan:PengYouQuan
{
    public MyselfPengYouQuan(string _userName):base(_userName)
    {

    }
}

调用:
     void Start()
     {
         //创建具体主题(此处就是我的朋友圈)
         MyselfPengYouQuan tempPengYouQuan = new MyselfPengYouQuan("此处有码");
         //加几个好友(将具体观察者增加到抽象主题的观察者队列中)
         Friend tempFriend1 = new YourSelfFriend("韩梅梅");
         Friend tempFriend2 = new YourSelfFriend("李雷");
         tempPengYouQuan.AddFriend(tempFriend1);
         tempPengYouQuan.AddFriend(tempFriend2);
         //我发了一个朋友圈,我的好友收到这个朋友圈
         tempPengYouQuan.PushInfo();
     }

运行结果:

以上是Subject(抽象主题)持有Observer(抽象观察者)的引用,然后通过ConcreteObserver(具体观察者)重写Observer(抽象观察者)的方法,在调用Observer(抽象观察者)的方法时候,继而调用到ConcreteObserver(具体观察者)的方法。

现在去掉Subject(抽象主题)持有持有Observer(抽象观察者)的引用,用Event实现。

//Observer(抽象观察者)
public abstract class Friend
{
    //点赞
    public abstract void GiveLike();
    //评论
    public abstract void Comment();
    //收到朋友圈信息
    public abstract void ReceiveInfo(string _friendName);
}

//ConcreteObserver(具体观察者)
public class YourSelfFriend:Friend
{
    public string m_userName{get;set;}

    public YourSelfFriend(string _userName)
    {
        m_userName = _userName;
    }

    public override void GiveLike()
    {
        Debug.Log(m_userName + "点了个赞");
    }
    public override void Comment()
    {
        Debug.Log(m_userName + "评论了你");
    }
    public override void ReceiveInfo(string _friendName)
    {
        Debug.Log(m_userName + "-收到朋友圈 来自:" + _friendName);
    }
}


//Subject(抽象主题)
public abstract class PengYouQuan
{
    public string m_userName{get;set;}

    public delegate void ReceiveInfo(string _userName);
    public event ReceiveInfo m_receiveEvent;

    public PengYouQuan(string _userName)
    {
        m_userName = _userName;
    }    

    //发布一条朋友圈,推送给好友
    public void PushInfo()
    {
        //有对象注册,调用所有添加到事件中的方法
        if(m_receiveEvent != null)
        {
            m_receiveEvent(m_userName);
        }
    }
}

//ConcreteSubject(具体主题)
public class MyselfPengYouQuan:PengYouQuan
{
    public MyselfPengYouQuan(string _userName):base(_userName)
    {

    }
}

调用:
     void Start()
     {
         //创建具体主题(此处就是我的朋友圈)
         MyselfPengYouQuan tempPengYouQuan = new MyselfPengYouQuan("此处有码");
         //加几个好友(将具体观察者增加到抽象主题的观察者队列中)
         Friend tempFriend1 = new YourSelfFriend("韩梅梅");
         Friend tempFriend2 = new YourSelfFriend("李雷");
         //持有观察者的引用,变成持有观察者的方法
         tempPengYouQuan.m_receiveEvent += tempFriend1.ReceiveInfo;
         tempPengYouQuan.m_receiveEvent += tempFriend2.ReceiveInfo;
         //tempPengYouQuan.AddFriend(tempFriend1);
         //tempPengYouQuan.AddFriend(tempFriend2);
         //我发了一个朋友圈,我的好友收到这个朋友圈
         tempPengYouQuan.PushInfo();
     }

参考:

https://www.cnblogs.com/libingql/p/3638453.html

https://www.cnblogs.com/JiYF/p/6896458.html

https://www.cnblogs.com/xmfdsh/p/4047114.html

https://blog.csdn.net/luxuheng/article/details/20302709

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值