你了解过观察者模式吗?
你了解过观察者模式吗?
题眼:本质上也是一种生产消费模型。
多数情况下会要求手写。
观察者模式(Observer Pattern)是一种设计模式,它定义了对象之间的依赖关系,使得当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并被自动更新。这种模式通常用于实现事件处理系统。
例如,假设我们有一个天气预报系统,其中一个对象负责检测天气条件(我们称其为“主题”)。然后,我们可能有多个显示设备(如手机应用、电视、广播等,我们称它们为“观察者”),需要在天气条件改变时更新显示的信息。在这种情况下,我们可以使用观察者模式:每当天气检测对象更新状态时,所有的显示设备都会收到通知,并更新其显示的信息。
参考答案:
观察者模型的话本质上也是一种生产者消费者模型,它是让多个观察者绑定到某个被观察者上,当被观察者的某个属性发生改变的时候能够及时做出相应。在具体实现上的话,观察者比较简单,它只需要实现一个OnCall方法,让被观察者调用就行了。被观察者实现起来比较麻烦,它需要维持一个观察者的队列,而且还得支持增加和删除。当被观察的事件触发的时候,遍历这个队列,然后依次调用这个他们的OnCall方法来实现操作。但是这样做,有一个比较麻烦的情况,观察者的队列里是串行操作的,如果某个方法耗时比较长会阻塞后面的方法。这里可以开协程或者线程并发通知,但是这样的话可能会起多个并发,增大开销,还有可能出BUG。最后的话,观察者模型我自己其实平常用的也不是特别多,主要是在做一些收尾工作的时候会用。比如说,订单已经结束,后续写购买记录,日志或者其他杂七杂八的工作,就会使用观察者来实现。
type Observer interface { // 观察者接口,也叫订阅者
OnCall(int) //触发响应的方法
}
type Notifier interface { // 被观察者,也叫发布者
Register(*Observer) //把一个观察者注册进来
Deregister(*Observer) //移除一个观察者,有些实现中没有移除的方法,这样会不完整,缺了一点灵活性
Notify(int) //发出消息,通知观察者们状态变化,int 来代表一个状态
}
// NotifierOne 实现一个发布者
type NotifierOne struct {
//observers []Observer //如果不需要移除操作,那么使用切片就好
observers map[Observer]struct{} //需要移除的话,显然使用MAP更合适。
//注意这里有两个细节,Key使用了interface,但是在接收的时候使用的是指针,Value是空结构体。我们之前都分享过这些细节。
status int //被观察的状态
}
func (n *NotifierOne) Register(o Observer) {
n.observers[o] = struct{}{} //将观察者装进Map
}
func (n *NotifierOne) Deregister(o Observer) {
delete(n.observers, o)
}
func (n *NotifierOne) Notify(status int) {
n.status = status
for observer, _ := range n.observers {
//逐个调用MAP中观察者的OnCall 方法,以此来实现通知操作。
observer.OnCall(status)
//这样也可以,通过并发的方式进行调用。但,任何问题只要开启并发,就会引入其他问题,需要提前想清楚
go observer.OnCall(status)
}
}
// Observer1 观察者1号
type Observer1 struct {
}
func (o *Observer1) OnCall(status int) {
//不同的观察者,可以做不同的事情,也可以做相同的事情。
fmt.Printf("关注香香编程喵喵喵!Status:%d\n", status)
}
// Observer2 观察者2号
type Observer2 struct {
}
func (o *Observer2) OnCall(status int) {
fmt.Printf("关注香香编程谢谢喵喵喵!Status:%d\n", status)
}
func testObs() {
//实例化一个被观察者
notifier := &NotifierOne{
observers: make(map[Observer]struct{}),
status: 0,
}
//实例化两个观察者
o1 := Observer1{}
o2 := Observer2{}
notifier.Register(&o1)
notifier.Register(&o2)
fmt.Printf("observers len:%d\n", len(notifier.observers)) // 2
//触发通知
notifier.Notify(1)
}
import java.util.ArrayList;
import java.util.List;
public class Subject {
private List<Observer> observers = new ArrayList<>();
public void registerObserver(Observer observer) {
observers.add(observer);
}
public void removeObserver(Observer observer) {
observers.remove(observer);
}
public void notifyObservers() {
for (Observer observer : observers) {
observer.update("Subject has been updated.");
}
}
}
public interface Observer {
void update(String message);
}
public class ConcreteObserver implements Observer {
private String name;
public ConcreteObserver(String name) {
this.name = name;
}
@Override
public void update(String message) {
System.out.println(name + " received: " + message);
}
}
