发布/订阅
现实中的观察者(Observer)往往是主动方,这是由于目标主题(Subject)缺乏主观能动性造成的,其状态的更新并不能主动地通知观察者,这就造成观察行为的持续往复。而在软件设计中我们可以将目标主题作为主动方角色,将观察者反转为被动方角色,建立反向驱动式的消息响应机制,以此来避免做无用功,优化软件效率
作为一种发布/订阅(publish/subscribe)式模型,观察者模式被大量应用于具有一对多关系对象结构的场景,它支持多个观察者订阅一个目标主题。一旦目标主题的状态发生变化,目标对象便主动进行广播,即刻对所有订阅者(观察者)发布全员消息通知,
基于这种一对多的关系网,观察者模式以多态化(泛型化)的方式弱化了目标主题与观察者之间强耦合的依赖关系,标准化它们的消息交互接口,并让主客关系发生反转,以“单方驱动全局”模式取代“多方持续轮询”模式,使目标主题(单方)的任何状态更新都能被即刻通过广播的形式通知观察者们(多方),解决了状态同步知悉的效率问题。
业务场景
商店的机票降价了?
未使用观察者模式,需要买家一直询问商店机票是否降价,往往需要耗费大量的无用功
引入观察者模式
观察者,买家,买家如果需要购买商店降价机票,需要在商店订阅机票情况
被观察者,商店机票价格,定义买家清单,后续机票降价时会通知所有订购的买家
以观察者为主动方的设计缺陷,大量无用功被消耗在状态交互上,举例机票是否降价,每次都得去点击刷新页面查看机票是否降价,频繁轮训处于被动状态,消耗大量无用功,换种做法,逆向思维,反客为主,当机票降价时,通知用户下单购买
这种反客为主的设计只需要一次握手协议并建立连接通道即可完成,之后发生的状态更新完全可以由服务端(被观察者)向Web客户端(观察者)进行消息推送的方式完成,这时就不会再有频繁轮询的情况发生了,交互效率问题迎刃而解

观察者模式的各角色定义如下
● Subject(目标主题):被观察的目标主题的接口抽象,维护观察者对象列表,并定义注册方法register()(订阅)与通知方法notify()(发布)。Shop
● ConcreteSubject(主题实现):被观察的目标主题的具体实现类,持有一个属性状态State,可以有多种实现。Shop
● Observer(观察者):观察者的接口抽象,定义响应方法update()。对应本章例程中的买家类Buyer。Buyer
● ConcreteObserver(观察者实现):观察者的具体实现类,可以有任意多个子类实现。收到通知后进行自己独特的处理。AirCustomer
实例代码
package com.azure.design.observer;
import java.util.ArrayList;
import java.util.List;
/**
* 商店类
*/
public class Shop {
private String product;
private List<Buyer> buyers; //预订清单
public Shop() {
this.product = "无降价";
this.buyers = new ArrayList<>();
}
//注册买家到预订清单中
public void register(Buyer buyer) {
this.buyers.add(buyer);
}
public String getproduct() {
return product;
}
public void setproduct(String product) {
this.product = product; //到货了
notifyBuyers(); //到货后通知买家
}
// 通知所有的买家
private void notifyBuyers() {
buyers.stream().forEach(b -> b.inform(this.getproduct()));
}
}
package com.azure.design.observer;
/**
* 买家抽象类
*/
public abstract class Buyer {
protected String name;
public Buyer(String name) {
this.name = name;
}
public abstract void inform(String product);
}
package com.azure.design.observer;
public class AirCustomer extends Buyer{
// 调用父类构造器
public AirCustomer(String name) {
super(name);
}
@Override
public void inform(String product) {
if(product.contains("机票")) {
System.out.print(name);
System.out.println("购买:" + product);
}
}
}
public class Client {
@Test
public void testObserverDemo() {
Buyer buyer = new AirCustomer("抢机票黄牛");
Shop shop = new Shop();
// 商店注册信息,预定
shop.register(buyer);
// 商店中机票降价
shop.setproduct("机票降价了");
}
}
程序输出
//抢机票黄牛购买:机票降价了
本文介绍了观察者模式在软件设计中的应用,通过将目标主题设置为主动方,观察者变为被动方,优化了一对多关系中的状态更新同步。以商店机票降价为例,说明了传统方式中买家频繁查询的低效,对比引入观察者模式后的高效通知机制。观察者模式包括Subject(目标主题)、ConcreteSubject(主题实现)、Observer(观察者)和ConcreteObserver(观察者实现)四个角色。代码示例展示了如何使用Java实现这一模式。
1071

被折叠的 条评论
为什么被折叠?



