观察者模式
当一个对象状态改变时,自动通知所有依赖它的对象,让它们自动更新
适用的场景
当对象之间是“一对多”关系,比如一人改动,多人知道 当你不想硬编码通知逻辑,让观察者自己决定怎么响应 当你希望事件解耦,让对象低耦合但联动灵活
例如:
游戏中角色属性变化 → UI 自动更新
状态改变 → 多个系统响应
基本结构
Subject(发布者):被观察者(发布者)注册、移除、通知观察者
Observer(观察者):抽象观察者接口,提供更新方法
ConcreteObserver(具体观察者):实际的响应者
ConcreteSubject(具体发布者):维护状态并通知变更
示例
csharp
interface IObserver
{
void Update(string message);
}
class Fan : IObserver
{
private string name;
public Fan(string name) => this.name = name;
public void Update(string message) => Console.WriteLine($"{name} 收到了通知:{message}");
}
class Idol
{
private List<IObserver> _fans = new();
public void AddFan(IObserver fan) => _fans.Add(fan);
public void RemoveFan(IObserver fan) => _fans.Remove(fan);
public void PostPhoto()
{
foreach (var fan in _fans)
fan.Update("我发新自拍啦");
}
}
// 使用:
var idol = new Idol();
idol.AddFan(new Fan("粉丝1号"));
idol.AddFan(new Fan("粉丝2号"));
idol.PostPhoto();在C#中,你也可以用事件和委托来实现观察者模式
csharp
// 定义委托类型
public delegate void NotificationHandler(string message);
class Fan
{
private string name;
public Fan(string name) => this.name = name;
// 这个方法符合NotificationHandler委托的签名
public void ReceiveNotification(string message)
=> Console.WriteLine($"{name} 收到了通知:{message}");
}
class Idol
{
// 定义事件
public event NotificationHandler OnPostPhoto;
public void PostPhoto()
{
// 触发事件
OnPostPhoto?.Invoke("我发新自拍啦");
}
}
// 使用:
var idol = new Idol();
var fan1 = new Fan("粉丝1号");
var fan2 = new Fan("粉丝2号");
// 订阅事件
idol.OnPostPhoto += fan1.ReceiveNotification;
idol.OnPostPhoto += fan2.ReceiveNotification;
idol.PostPhoto();
// 取消订阅示例
// idol.OnPostPhoto -= fan1.ReceiveNotification;GDScript示例
gdscript
class Observer:
func update(msg: String) -> void:
pass
class Listener extends Observer:
var name: String
func _init(name: String):
self.name = name
func update(msg: String):
print(name, "收到:", msg)
class ButtonPublisher:
var observers = []
func add_observer(o: Observer):
observers.append(o)
func click():
for o in observers:
o.update("按钮被点击啦!")
# 使用:
func _ready():
var button = ButtonPublisher.new()
button.add_observer(Listener.new("监听者1号"))
button.add_observer(Listener.new("监听者2号"))
button.click()在GDScript中,你也可以用信号和可调用体来实现观察者模式
gdscript
class Listener:
var name: String
func _init(name: String):
self.name = name
func update(msg: String):
print(name, "收到:", msg)
class ButtonPublisher:
# 定义信号
signal button_clicked(message: String)
func click():
# 发送信号
button_clicked.emit("按钮被点击啦!")
# 使用:
func _ready():
var button := ButtonPublisher.new()
var listener1 := Listener.new("监听者1号")
var listener2 := Listener.new("监听者2号")
# 连接信号
button.button_clicked.connect(listener1.update)
button.button_clicked.connect(listener2.update)
button.click()
# 断开信号示例
# button.button_clicked.disconnect(listener1.update)