当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。
比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。
来自菜鸟编程:http://www.runoob.com/design-pattern/observer-pattern.html
事例: 模拟发布/订阅消息
功能实现:即时消息,延时消息,
生产者(被观察对象):
负责接收消息
package com.designPattern.service;
import com.designPattern.api.ObserverConsumer;
import java.util.HashMap;
import java.util.Map;
/**
* 观察者模式
* 生产者(被监听)
* Created by h on 2019/3/20.
*/
public class ObserverProducer {
private Map<String, ObserverConsumer> map = new HashMap();
public ObserverProducer() {
map.put("order", new ObserverConsumerOrder());
map.put("delayed", new ObserverConsumerDelayed());
}
public void send(String topic, String message) {
if (topic == null || topic.length() == 0) {
new Exception("err-主题不能为空...");
}
ObserverConsumer observerConsumer = map.get(topic);
if (observerConsumer == null) {
new Exception("err-找不到对应主题...");
}
observerConsumer.message(message, 0);
}
public void send(String topic, String message, int delayed) {
if (delayed == 0) {
send(topic, message);
return;
}
if (topic == null || topic.length() == 0) {
new Exception("err-主题不能为空...");
}
ObserverConsumerDelayed observerConsumer = (ObserverConsumerDelayed)map.get(topic);
if (observerConsumer == null) {
new Exception("err-找不到对应主题...");
}
observerConsumer.messageMap(message, delayed);
}
}
消费者(观察员):
负责消费消息
package com.designPattern.api;
/**
* 观察者模式
* 消费者接口
* Created by h on 2019/3/20.
*/
public interface ObserverConsumer {
void message(String message, int delayed);
}
package com.designPattern.service;
import com.designPattern.api.ObserverConsumer;
/**
* 观察者模式
* 即时消息消费者(监听者)
* Created by h on 2019/3/20.
*/
public class ObserverConsumerOrder implements ObserverConsumer{
@Override
public void message(String message, int delayed) {
System.out.println("order---》收到消息:" + message);
}
}
package com.designPattern.service;
import com.designPattern.api.ObserverConsumer;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* 观察者模式
* 延时消息消费者(监听者)
* Created by h on 2019/3/20.
*/
public class ObserverConsumerDelayed implements ObserverConsumer{
private Map<String, List<String>> map = new HashMap<>();
public ObserverConsumerDelayed() {
listen();
}
@Override
public void message(String message, int delayed) {
new Thread(()->{
try {
Thread.sleep(delayed);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("order---》收到消息:" + message);
}).start();
}
public void messageMap(String message, int delayed) {
long millis = delayed + System.currentTimeMillis();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String date = sdf.format(millis);
System.out.println("延时执行时间:" + date);
if (map.containsKey(date)) {
map.get(date).add(message);
} else {
List<String> list = new ArrayList<>();
list.add(message);
map.put(date, list);
}
}
public void listen() {
System.out.println("开始监听:----");
new Thread(()->{
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String dateStr = sdf.format(date);
List<String> list = map.get(dateStr);
if (list == null || list.size() == 0) {
continue;
}
for (String s:list) {
System.out.println("delayed---》收到消息:" + s + ",执行时间:" + dateStr);
}
}
}).start();
}
}
测试代码:
package com.designPattern.test;
import com.designPattern.service.ObserverProducer;
/**
* 观察者模式
* Created by h on 2019/3/20.
*/
public class ObserverTest {
public static void main(String[] args) {
ObserverProducer observerProducer = new ObserverProducer();
observerProducer.send("order", "我是顺序消息.");
for (int i = 1; i < 5; i++) {
observerProducer.send("delayed", "我是延时消息."+i, i*1000);
}
}
}
打印结果:
开始监听:----
order---》收到消息:我是顺序消息.
延时执行时间:2019-03-21 12:05:08
延时执行时间:2019-03-21 12:05:09
延时执行时间:2019-03-21 12:05:10
延时执行时间:2019-03-21 12:05:11
delayed---》收到消息:我是延时消息.1,执行时间:2019-03-21 12:05:08
delayed---》收到消息:我是延时消息.2,执行时间:2019-03-21 12:05:09
delayed---》收到消息:我是延时消息.3,执行时间:2019-03-21 12:05:10
delayed---》收到消息:我是延时消息.4,执行时间:2019-03-21 12:05:11
小结:实现ObserverConsumer接口的类为观察者,也就是观察ObserverProducer接收到的消息。
若有理解不到位的地方希望大家能够指点一下,也避免让别人犯错。非常感谢!!!