观察者模式 也叫做订阅发布模式。
观察者模式定义了对象之间的一对多依赖,让多个观察者对象同时监听一个主体对象,当主体对象发生变化时,它的所有依赖者都会收到通知并更新。
简单理解观察者模式
创建一个餐厅Kitchen.java(被观察类)
public class Kitchen extends Observable {
private String name="天天中餐厅";
private static Kitchen kitchen;
private Kitchen(){}
public String getName() {return this.name;}
public static Kitchen getInstance() {
if(kitchen != null) {
return kitchen;
}
return new Kitchen();
}
public void dishOut(Food food) {
System.out.println();
System.out.println(name+"出菜了!菜名:"+food.getName()+";价格:"+food.getPrice()+";");
setChanged();
notifyObservers(food);
}
}
创建服务员Waiter.java(观察者类)
public class Waiter implements Observer {
private String name;
public Waiter(String name) {
this.name = name;
}
@Override
public void update(Observable o, Object arg) {
Food food = (Food) arg;
if(food.getIsOut() == 0) {
System.out.println("==================================================================");
System.out.println("服务员"+this.name+"将"+food.getName()+"端到"+food.getNumber()+"号桌");
food.setIsOut(1);
}
}
}
创建菜品类Food.java
public class Food {
private String name;
private double price;
private int number;
private int isOut = 0;
public Food(String name, double price, int number) {
this.name = name;
this.price = price;
this.number = number;
}
public int getIsOut() {
return isOut;
}
public void setIsOut(int isOut) {
this.isOut = isOut;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
测试类
public static void main(String[] args) {
Kitchen kitchen = Kitchen.getInstance();
Food fish = new Food("酸菜鱼", 68.99, 200);
Food tofu = new Food("麻辣豆腐", 18, 200);
kitchen.addObserver(new Waiter("小王"));
kitchen.dishOut(fish);
kitchen.addObserver(new Waiter("小米"));
kitchen.dishOut(tofu);
}
输出结果

使用Guava快速搭建观察者模式
导入依赖
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>28.1-jre</version>
</dependency>
通过**@Subscribe**订阅消息
public class Waiter {
private String name;
public Waiter(String name) {
this.name = name;
}
@Subscribe
public void dishOut(Food food) {
System.out.println("==================================================================");
System.out.println("服务员"+this.name+"将"+food.getName()+"端到"+food.getNumber()+"号桌");
}
}
测试类,通过EventBus消息总线类广播消息
public static void main(String[] args) {
EventBus bus = new EventBus();
bus.register(new Waiter("小东"));
bus.register(new Waiter("小飞"));
bus.post(new Food("酸菜鱼", 68.99, 200));
}
输出结果与JDK观察者模式类似

手写JS鼠标事件回调
Callback.java
通过callback接口钩子动态注册具体的事件回调函数。
public interface Callback {
public void callback();
}
Event.java
事件类,管理回调函数以及事件源等信息。
public class Event {
private Object source;
private Object target;
private Callback callback;
private String trigger;
private long time;
public Event(Object target, Callback callback) {
this.target = target;
this.callback = callback;
}
public Event setSource(Object source) {
this.source = source;
return this;
}
public Event setTime(long time) {
this.time = time;
return this;
}
public Event setTrigger(String trigger) {
this.trigger = trigger;
return this;
}
public Object getSource() {
return this.source;
}
public String getTrigger() {
return this.trigger;
}
public long getTime() {
return this.time;
}
public Callback getCallback() {
return this.callback;
}
}
EventListener.java
定义监听类,通过events的Map去管理所有注册的监听事件。该类为监听事件管理的类。
public class EventListener {
private Map<String, Event> events = new HashMap<>();
public void addListener(Object target, String trigger, Callback callback) {
addListener(trigger, new Event(target, callback));
}
public void addListener(String trigger, Event event) {
events.put(trigger, event);
}
public void trigger(String trigger) {
if(!events.containsKey(trigger)) throw new RuntimeException("Can't find callback...");
events.get(trigger).getCallback().callback();
}
}
MouseEventKey.java
事件监听key --对应-- 事件Event,重复注册监听事件会覆盖之前注册的事件。
public interface MouseEventKey {
public static final String ON_CLICK = "click";
public static final String ON_MOVE = "move";
public static final String ON_BLUR = "blur";
public static final String ON_DOUBLE_CLICK = "doubleclick";
}
Mouse.java
集成EventListener类,通过addListener方法注册鼠标监听事件。通过拓展方法调用具体的鼠标监听事件。
public class Mouse extends EventListener {
public void addListener(Object target, String trigger, Callback callback) {
super.addListener(target, trigger, callback);
}
public void click() {
super.trigger(MouseEventKey.ON_CLICK);
}
public void move() {
super.trigger(MouseEventKey.ON_MOVE);
}
public void doubleClick() {
super.trigger(MouseEventKey.ON_DOUBLE_CLICK);
}
public void blur() {
super.trigger(MouseEventKey.ON_BLUR);
}
}
测试
public static void main(String[] args) {
Mouse mouse = new Mouse();
mouse.addListener(null, MouseEventKey.ON_CLICK, new Callback() {
@Override
public void callback() {
System.out.println("mouse click callback...");
}
});
mouse.addListener(null, MouseEventKey.ON_DOUBLE_CLICK, new Callback() {
@Override
public void callback() {
System.out.println("mouse double click callback...");
}
});
mouse.click();
mouse.doubleClick();
mouse.move();
}
输出结果

因为鼠标移动事件未注册监听事件,所以会报一个RuntimeException的异常错误。
315

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



