观察者模式
当对象存在一对多的关系时,可以考虑使用观察者模式(Observer Pattern)
意图: 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖与他的对象都得到通知并自动更新。
主要解决: 一个对象状态改变如何通知其他对象的问题,而且要考虑到易用和低耦合,保证高度协作
如何解决: 使用面向对象技术,可以将这种依赖关系弱化
关键代码: 用一个ArrayList存放观察者们
应用实例:
- 拍卖的时候,拍卖师观察最高标价,然后通知其他竞价者竞价
- 前台观察老板来否,通知同事停止摸鱼开始干活;
优点:
- 观察则与被观察者时抽象耦合的
- 建立一套触发机制;
缺点:
3. 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者通知会到会花费很多时间
4. 如果被观察者和观察者之间有循环依赖的话,观察目标会触发他们之间的循环调用,可能导致系统崩溃
5. 观察者模式没有相应的机制让观察者知道被观察者是怎么发生变化的,而仅仅只是知道被观察者发生了变化
6. 具体的观察者,通知方法被固定了
代码实例
猫叫老鼠跑主人醒
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ModelView : MonoBehaviour
{
private void Start()
{
Cat cat= new Cat();
Mouse mouse= new Mouse();
Master master = new Master();
cat.Add(mouse);
cat.Add(master);
cat.Cry();
}
}
//观察者接口
public interface IObservers
{
void Response();
}
//被观察者接口
public interface ISubject
{
void Add(IObservers obs);
}
//老鼠观察者
public class Mouse : IObservers
{
public void Response()
{
Debug.Log("老鼠跑了!");
}
}
//主人观察者
public class Master : IObservers
{
public void Response()
{
Debug.Log("主人醒了!");
}
}
//猫被观察者
public class Cat : ISubject
{
//观察者链表,存储所有观察者
private List<IObservers> observers= new List<IObservers>();
//观察者入链
public void Add(IObservers obs)
{
observers.Add(obs);
}
public void Cry()
{
Debug.Log("猫叫了!");
//猫的状态由正常变为猫叫时,遍历链表,通知观察者改变自己的状态
foreach(IObservers obs in observers)
{
obs.Response();
}
}
}
C#事件委托
观察者模式中观察者的行为高度依赖被观察者,要实现解耦,就需要委托
委托
其实就是定义了一个东西来存放要同时触发的方法,当执行委托方法的时候,委托对象里的方法自动执行
事件
事件是一种特殊签名的委托,本意是对委托的封装,它只能在外部被订阅,不能在外部被触发 ,所以只能以内部的公开方法,在方法内触发事件,这样可以使得程序更加安全。
委托方法可以直接调用
事件委托方法只能在类内部的公有接口中调用,再从外部调用这个接口
代码实例
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EventDelegate : MonoBehaviour
{
private void Start()
{
Cat2 cat2 = new Cat2();
Mouse2 mouse2 = new Mouse2();
Master2 master2 = new Master2();
cat2.ievent+= mouse2.Response;
cat2.ievent+= master2.Response;
//cat2.ievent(); //委托方法直接调用
cat2.RunEvent(); //事件委托须通过共有接口内部调用
}
}
//声明委托
public delegate void IEvent();
public class Cat2
{
//public IEvent ievent; //委托
public event IEvent ievent; //事件委托
public void RunEvent()
{
Debug.Log("猫叫了!!!!!!!");
ievent();
}
}
public class Mouse2
{
public void Response()
{
Debug.Log("老鼠跑了!");
}
}
public class Master2
{
public void Response()
{
Debug.Log("主人醒了!");
}
}
同样的功能,使用委托非常简洁,并且被观察者类里没有任何观察者类成员,两者是完全独立的。
观察者不需要继承观察者接口,它的通知方法名字可以不同,比如说人的执行方法可以是Notify,猫的执行方法可以是Run
观察者模式存在的意义就是解耦,它使观察者和被观察者的逻辑彼此独立,互不依赖。而使用委托则能使观察者和被观察者完全解耦,甚至不需要知道被观察者的存在