Unity_设计模式_观察者模式_08

来源:互联网 发布:mac 刻录机 编辑:程序博客网 时间:2024/05/22 06:20

软件系统:一个对象的状态或行为的变化将导致其他对象的状态或行为也发生改变,它们之间将产生联动
观察者模式:
定义了对象之间一种一对多的依赖关系,让一个对象的改变能够影响其他对象。
发生改变的对象称为观察目标,被通知的对象称为观察者
一个观察目标可以对应多个观察者。
定义
观察者模式:定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象都得到通知并被自动更新。对象行为型模式。
别名
发布-订阅(Publish/Subscribe)模式
模型-视图(Model/View)模式
源-监听器(Source/Listener)模式
从属者(Dependents)模式
结构
这里写图片描述
观察者模式包含以下4个角色:
Subject(目标)
ConcreteSubject(具体目标)
Observer(观察者)
ConcreteObserver(具体观察者)
代码
典型的抽象目标类代码:
using System.Collection
abstract class Subject
{
//定义一个观察者集合用于存储所有观察者对象
protected ArrayList observers = new ArrayList();
//声明抽象注册方法,用于向观察者集合中增加一个观察者
public abstract void Attach(Observer observer);
//声明抽象注销方法,用于在观察者集合中删除一个观察者
public abstract void Detach(Observer observer);
//声明抽象通知方法
public abstract void Notify();
}

典型的具体目标类代码:
class ConcreteSubject : Subject
{
public override void Attach(Observer observer)
{
observers.Add(observer);
}
public override void Detach(Observer observer)
{
observers.Remove(observer);
}
//实现通知方法
public override void Notify()
{
//遍历观察者集合,调用每一个观察者的响应方法
foreach(object obs in observers)
{
((Observer)obs).Update();
}
}
}

典型的抽象观察者代码:
interface Observer
{
void Update();
}

典型的具体观察者代码:
class ConcreteObserver : Observer
{
//实现响应方法
public void Update()
{
//具体更新代码
}
}
典型的客户端代码片段:
……
Subject subject = new ConcreteSubject();
Observer observer = new ConcreteObserver();
subject.Attach(observer);
subject.Notify();
……
注意
有时候在具体观察者类ConcreteObserver中需要使用到具体目标类ConcreteSubject中的状态(属性),会存在关联或依赖关系
如果在具体层之间具有关联关系,系统的扩展性将受到一定的影响,增加新的具体目标类有时候需要修改原有观察者的代码,在一定程度上违背了开闭原则,但是如果原有观察者类无须关联新增的具体目标,则系统扩展性不受影响。
实例说明
RPG游戏中,当我们拾取一个物品时,我们需要做一些什么事?播放一个拾取获得的音效,一个UI显示你获得了XXX道具,你的游戏背包里实时进行了更新,播放一个拾取的动画等,这样是不是我们的拾取的一个动作,触发了一系列的事件,只要我们不拾取物品,这些事件就不会进行触发,说明有东西在实时监测我们是否拾取东西,一旦拾取就要进行一系列的事件触发和逻辑判断。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ObserverModel
{
class Program
{
static void Main(string[] args)
{
BeObservered bo = new BeObservered();
//注册观察者
bo.AddIObserver(new GetProp());
bo.AddIObserver(new AnimationPlay());
bo.AddIObserver(new SoundPlay());
bo.AddIObserver(new KnapsackSystem());
//之前注册事件的触发
bo.Nodify();
}
}
//一个观察者的接口
public interface IObserver
{
void TriggerEvent();
}
//被观察的对象,一旦这个对象发生了某些变化,就通知所有注册了观察他的对象
public class BeObservered
{
List list = new List();
//添加观察者
public void AddIObserver(IObserver ob)
{
list.Add(ob);
}
//移除观察者
public void RemoveIObserver(IObserver ob)
{
list.Remove(ob);
}
//通知所有的注册过的观察者
public void Nodify()
{
for (int i = 0; i < list.Count; i++)
{
list[i].TriggerEvent();
}
}
}
//UI弹窗,提示获得道具的观察者
public class GetProp : IObserver
{
public void TriggerEvent()
{
Console.WriteLine(“弹出对话框,获得XXX道具”);
}
}
//拾取道具动画的观察者
public class AnimationPlay : IObserver
{
public void TriggerEvent()
{
Console.WriteLine(“播放一个拾取的动画”);
}
}
//背包系统的观察者
public class KnapsackSystem : IObserver
{
public void TriggerEvent()
{
Console.WriteLine(“配包系统里的道具数量加一”);
}
}
//声音播放的观察者
public class SoundPlay : IObserver
{
public void TriggerEvent()
{
Console.WriteLine(“播放一个获得道具的音效”);
}
}
}
观察者模式与.NET中的委托事件模型
事件源对象充当观察目标角色,委托对象充当抽象观察者角色,事件处理对象充当具体观察者角色。
如果事件源对象的某个事件触发,则调用事件处理对象中的事件处理程序来对事件进行处理。
模式优点
可以实现表示层和数据逻辑层的分离。
在观察目标和观察者之间建立一个抽象的耦合。
支持广播通信,简化了一对多系统设计的难度。
符合开闭原则,增加新的具体观察者无须修改原有系统代码,在具体观察者与观察目标之间不存在关联关系的情况下,增加新的观察目标也很方便。
模式缺点
将所有的观察者都通知到会花费很多时间。
如果存在循环依赖时可能导致系统崩溃。
没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而只是知道观察目标发生了变化。
模式使用环境
一个抽象模型有两个方面,其中一个方面依赖于另一个方面,将这两个方面封装在独立的对象中使它们可以各自独立地改变和复用。
一个对象的改变将导致一个或多个其他对象发生改变,且并不知道具体有多少对象将发生改变,也不知道这些对象是谁。
需要在系统中创建一个触发链。

原创粉丝点击