【unity】观察者模式
什么是观察者模式
观察者模式适用于一对多的应用场景。
有若干观察者对象,他们依赖于目标对象。当目标对象执行某操作时,所有观察者对象都会得到通知并自动执行相应操作。
举个例子:在老头环中,只要玩家喝血瓶,那么周围的敌人就会捕获到这个动作,并立刻发动进攻,让你喝多少吐多少。
在上述例子里,玩家就是“目标对象”;周围所有的敌人就是“观察者对象”。玩家喝血即“目标对象执行某操作”,而所有敌人都会接收到玩家喝血的广播,然后立刻发动攻击,即“执行对应操作”。
实现手段
在说实现手段前,我还是想强调:设计模式始终是思想,具体的实现手段各不相同。
这里我使用事件来实现,你也可以让目标持有所有观察者的引用来实现等等。
定义一个抽象目标基类 BaseSubject ,其他目标类均继承自它
public abstarct class BaseSubject
{
public event Action CallObservers;
public void CallAllObservers()
{
CallObservers?.Invoke();
}
}
定义一个抽象观察者基类 BaseObserver ,其他目标类均继承自它
public abstarct class BaseObserver
{
public abstract void OnEnable();
public abstract void OnDisable();
public abstract void UpdateMyState();
}
某个目标类,继承自抽象目标基类
public class Subject : BaseSubject
{
private void Start()
{
ChangeState();
}
public void ChangeState()
{
Debug.Log("Player(Subject) : Drink to heal myself.");
CallAllObservers();
}
}
某个观察者类,继承自抽象观察者基类
public class Observer : BaseObserver
{
public BaseSubject subject;
public override void OnEnable()
{
subject.CallObservers += UpdateMyState;
}
public override void OnDisable()
{
subject.CallObservers -= UpdateMyState;
}
public override void UpdateMyState()
{
Debug.Log("Enemy(Observer) : Attack right now!");
}
}
结果如下
优缺点
优点:
- 它降低了对象之间的耦合度,方便使用。
- 它建立起了一套触发机制,使得不同的观察者均可以很好地响应目标的广播,方便代码拓展。
- 符合迪米特法则(最少知道原则)。
缺点:
- 当观察者数量过多时,整体响应时间较长。
- 观察者无从得知目标变化的具体内容,它仅仅知道目标发生了变化。
在老头环里,部分玩家反过来利用了这一点。在玩家装填弩箭时,敌人也会“读指令”,但装填弩箭的前后摇比喝药的前后摇短很多,敌人却无从得知玩家变化的具体内容,仅仅知道玩家卖了个破绽,所以当敌人攻击时,玩家已经可以发动弹反来反击了。 - 当观察者与目标间有循环依赖时,可能发生循环调用致使系统崩溃。
注意:
- 观察者模式适用于一对多的应用场景。
小结
值得一提的是,观察者模式尤为契合解谜游戏的需求,采取该模式进行设计开发,可以很大程度上降低开发难度。