观察者模式
当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式。
介绍
意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。
何时使用:一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。
如何解决:使用面向对象技术,可以将这种依赖关系弱化。
关键代码:在抽象类里有一个 ArrayList 存放观察者们。
应用实例: 1、拍卖的时候,拍卖师观察最高标价,然后通知给其他竞价者竞价。 2、西游记里面悟空请求菩萨降服红孩儿,菩萨洒了一地水招来一个老乌龟,这个乌龟就是观察者,他观察菩萨洒水这个动作。
优点: 1、观察者和被观察者是抽象耦合的。 2、建立一套触发机制。
缺点: 1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。 2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。 3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
使用场景:
注意事项: 1、JAVA 中已经有了对观察者模式的支持类。 2、避免循环引用。 3、如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。
美团为可观察者(主题)
骑手,商家,吃货为观察者
根据订单改变,通知所有注册过的观察者
(最近项目中使用多线程sftp实现上传下载,如果线程因为某种原因死了,会进行重新开启线程执行,就可以通过观察者模式来实现)
package xyz.hashdog.observer;
/**
* 可观察者
*/
public interface Observable {
/**
* 注册观察者
* @param observer
*/
void addObserver(Observer observer);
/**
* 删除观察者
* @param observer
*/
void delObserver(Observer observer);
/**
* 通知
*/
void notifyObserver();
}
package xyz.hashdog.observer;
import java.util.Map;
/**
* 观察者
*/
public interface Observer {
/**
* 当数据改变时被调用
* @param map
*/
void update(Map map);
}
package xyz.hashdog.observer;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class Meituan implements Observable {
/**
* 存放注册的观察者
*/
private List observers = new ArrayList<>();
/**
* 模拟订单
*/
private Map order;
@Override
public void addObserver(Observer observer) {
observers.add(observer);
}
@Override
public void delObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObserver() {
observers.forEach(e->e.update(order));
}
public Map getOrder() {
return order;
}
/**
* 订单改变之后,通知观察者
* @param order
*/
public void setOrder(Map order) {
this.order = order;
notifyObserver();
}
}
骑手
package xyz.hashdog.observer;
import java.util.Map;
/**
* 骑手
*/
public class Qishou implements Observer {
@Override
public void update(Map map) {
if(map.get("state").equals("商家已做好")){
System.out.println("骑手发货");
}else if(map.get("state").equals("下单")){
System.out.println("骑手抢单");
}else {
System.out.println("没骑手什么事儿");
}
}
}
商家
package xyz.hashdog.observer;
import java.util.Map;
public class Shangjia implements Observer {
@Override
public void update(Map map) {
if(map.get("state").equals("下单")){
System.out.println("做饭");
}else{
System.out.println("商家啥都不做");
}
}
}
package xyz.hashdog.observer;
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) throws InterruptedException {
Meituan meituan = new Meituan();
Observer shangjia = new Shangjia();
Observer qishou = new Qishou();
meituan.addObserver(shangjia);
meituan.addObserver(qishou);
//新注册个吃货
meituan.addObserver(new Observer() {
@Override
public void update(Map map) {
if(map.get("state").equals("已发货")){
System.out.println("收货,吃吃吃");
}else{
System.out.println("吃货什么都不用做");
}
}
});
Map order = new HashMap();
order.put("state","下单");
order.put("commodity","奶茶");
meituan.setOrder(order);
Thread.sleep(5*1000);
System.out.println("******************改变订单*************");
Map updateOrder = meituan.getOrder();
updateOrder.put("state","商家已做好");
meituan.setOrder(updateOrder);
Thread.sleep(5*1000);
System.out.println("******************改变订单*************");
Map updateOrder2 = meituan.getOrder();
updateOrder.put("state","已发货");
meituan.setOrder(updateOrder);
}
}
https://download.csdn.net/download/corleone_4ever/12552054