0.前言
有人把观察者(Observer)模式等同于发布(Publish)/订阅(Subscribe)模式,也有人认为这两种模式还是存在差异,但总体来说差异并不大。
实际生活中,发布/订阅模式较为常见,接触比较多的是会员用户扫码关注了某店铺微信小程序。比如说:
A同学关注了 李宁运动店铺
B同学关注了 必胜客披萨店
C同学则两家都关注了
于是,当球鞋换季时,A和C可以收到李宁店铺的广告;Pizza出新品菜单,B和C又可以收到推荐及时尝鲜。
1.店铺类
店铺必须具备2个功能:
1.持有会员,方面后期管理,得知道哪些客户关注了店铺
2.店铺得发布通知,告知会员
创建抽象类 Shop
/**
* Shop 普通店铺
*
* @author: 喵掌柜
*/
public abstract class Shop {
// 持有的顾客列表
private List<Customer> customerList = new ArrayList<>();
/** 发布内容 */
public void notify(String messageStr) {
// 待实现
}
}
使用 private 修饰 customerList,表示 客户信息是店铺的内部数据,不会暴漏给外部的
2.客户类
客户需要具有订阅能力,获得店铺最新消息
/**
* Customer
*
* @author: 喵掌柜
*/
public abstract class Customer {
/** 订阅某店铺 */
public void subscribe(Shop shop){
// 待实现
}
/** 阅读来自某店铺的推广、通知 */
public void getMessage(Shop shop){
// 待实现
}
}
3.完善订阅
店铺类 Shop 需要一个接口方法(可类比于二维码),帮助客户 Customer 完成订阅
/** Shop 类订阅方法 */
public void attach(Customer... customers) {
for (Customer customer : customers) {
customerList.add(customer);
}
}
客户 Customer 完成订阅方法
/** Customer 订阅某店铺 */
public void subscribe(Shop shop){
shop.attach(this);
}
4.完善发布
店铺类 Shop 的通知方法,店员会使用它发布新通知
/** Shop 发布内容 */
public void notify(String messageStr) {
// 把消息逐一发送给订阅的客户
customerList.forEach(customer -> {
customer.getMessage(messageStr);
});
}
订阅的客户拿到消息后,直接打印到屏幕上就行
/** Customer 阅读来自某店铺的推广、通知 */
public void getMessage(String message){
// 正常打印即可
System.out.println(message);
}
5.其他完善
给店铺、顾客都起个名字吧,好分辨,完整的如下:
public abstract class Shop {
private String name;
public Shop(String name){
this.name = name;
}
// 持有得顾客列表
private List<Customer> customerList = new ArrayList<>();
/** 订阅方法 */
public void attach(Customer... customers) {
for (Customer customer : customers) {
customerList.add(customer);
}
}
/** 发布内容 */
public void notify(String messageStr) {
// 把消息逐一发送给订阅用户
customerList.forEach(
customer -> {
System.out.println("消息来自:" + this.name);
customer.getMessage(messageStr);
});
}
}
李宁和披萨店
public class LiNingShop extends Shop{
public LiNingShop() {
super("LiNing");
}
}
public class PizzaShop extends Shop{
public PizzaShop() {
super("Pizza");
}
}
顾客类
@Data
@AllArgsConstructor
public class Customer {
private String name;
/** 订阅某店铺 */
public void subscribe(Shop shop){
shop.attach(this);
}
/** 阅读来自某店铺的推广、通知 */
public void getMessage(String message){
// 正常打印即可
System.out.println("接收者:" + this.name);
System.out.println("消息内容:" + message);
System.out.println("##########################");
}
}
6.main方法以及结果
public static void main(String[] args) {
LiNingShop liNingShop = new LiNingShop();
PizzaShop pizzaShop = new PizzaShop();
Customer customerA = new Customer("小A");
Customer customerB = new Customer("小B");
Customer customerC = new Customer("小C");
// A、C订阅李宁店
customerA.subscribe(liNingShop);
customerC.subscribe(liNingShop);
// B、C订阅披萨店
customerB.subscribe(pizzaShop);
customerC.subscribe(pizzaShop);
// 各个店铺发布变更消息
liNingShop.notify("新款运动鞋到货");
pizzaShop.notify("pizza推出美味新品");
}
结果,A、C收到李宁店的消息,B、C收到pizza店的消息
消息来自:LiNing
接收者:小A
消息内容:新款运动鞋到货
##########################
消息来自:LiNing
接收者:小C
消息内容:新款运动鞋到货
##########################
消息来自:Pizza
接收者:小B
消息内容:pizza推出美味新品
##########################
消息来自:Pizza
接收者:小C
消息内容:pizza推出美味新品
##########################