还是《Game.Programming.Patterns》一书中对观察者模式的个人理解,惯例看一下菜鸟教程的描述:

观察者模式应用的也比较多了,各大框架中的消息/通知/事件(叫法多样),很多就是用的观察者模式,或者在此基础上结合多种设计模式 ··· ···
实现:玩家在桥上失足掉入河中,达成成就~ (233333)
public enum ActorEvent
{
fellOffBridge,
}
//角色基类
public class Actor
{
}
//观察者基类(通知/消息/事件)
public abstract class Observer
{
//接收通知
public abstract void OnNotify(Actor actor, ActorEvent actorEvent);
}
//观察者链表节点
public class ObserverNode
{
//下一节点
public ObserverNode next;
//节点对应的观察者
public Observer observer { get; private set; }
//构造函数
public ObserverNode(Observer relatedOnserver)
{
observer = relatedOnserver;
next = null;
}
}
//被观察者基类
public class Subject
{
改进前
观察者列表
//被观察者需要保存所有的观察者, 不论采用哪种数据结构, 增删观察者需要分配内存
//List<Observer> observerList = new List<Observer>();
初次改进
改用链式结构, 由观察者自己记录, 观察者的多少无太大影响, 无需动态内存
这样的方式也有缺点! 一个被观察者 可以有多个观察者, 但一个观察者 只能有一个被观察对象, 不能同时对应多个观察者, 类似于线性结构
//protected Observer observer;
//再次改进
//记录观察者节点, 而不是记录和观察者, 不同的被观察者有不同的节点, 不同节点可以指向同一个观察者, 类似于网状结构
protected ObserverNode head;
public Subject()
{
head = null;
}
//添加观察者节点, 将其插入到链表的首位, 这样被观察者依次给观察者通知时, 会与添加顺序相反
//如果将新加项添加到链表末位, 需要遍历整个链表直到最末位, 效率相对较慢
//如果各个观察者之间不存在耦合, 通知的先后顺序不会发生任何影响
public void AddObserver(ObserverNode node)
{
node.next = head;
head = node;
}
//删除观察者节点, 删除操作需要遍历整个链表, 显然这种操作不够优雅, 可以尝试双向链表~
public void DeleteObserver(ObserverNode node)
{
//如果要删除项在首位, head指向下一个, 删除首位next引用
if (head == node)
{
head = node.next;
node.next = null;
return;
}
//如果要删除项不在首位, 遍历链表
ObserverNode curNode = head;
while (curNode != null)
{
//剔除当前项, 将上一个的引用指向下一个
if (curNode.next == node)
{
curNode.next = node.next;
node.next = null;
return;
}
curNode = curNode.next;
}
}
//删除所有观察者节点
除了循环删除引用, 还可以定义一条特定的Notify通知, 需要删除是通知观察者, 观察者自行注销
public void DeleteAllObserver()
{
//遍历删除所有节点的next
ObserverNode curNode = head;
while (curNode.next != null)
{
head = curNode.next;
curNode.next = null;
curNode = head;
}
head = null;
}
//通知观察者
protected void Notify(Actor actor, ActorEvent actorEvent)
{
//遍历所有节点, 调用节点的观察者接收函数
ObserverNode curNode = head;
while (curNode != null)
{
curNode.observer.OnNotify(actor, actorEvent);
curNode = curNode.next;
}
}
}
//成就, 观察者
public class Achievements
{
public void OnNotify(Actor actor, ActorEvent actorEvent)
{
if (IsHero(actor))
UnLock(actorEvent);
}
void UnLock(ActorEvent actorEvent)
{
}
bool IsHero(Actor actor)
{
return true;
}
}
//物理系统, 被观察者
public class Physics : Subject
{
Actor player = new Actor();
void UpdateMovement()
{
if (true)
Notify(player, ActorEvent.fellOffBridge);
}
}
本文来自博客园,作者:萧然CS,转载请注明原文链接:https://www.cnblogs.com/z-c-s/p/15112983.html
浙公网安备 33010602011771号