一、什么是订阅发布模式
订阅发布模式定义了一种 一对多 的依赖关系,一指发布者,比如某个主题对象,多指订阅者,依赖是订阅者对发布者的依赖;多个订阅者同时监听一个主题对象。当发布者即主题对象的状态发生变化时,会将该变化通知给订阅者,订阅者据此更新自己的状态。是设计模式中用的比较多的一种。
二、为什么使用订阅发布模式
订阅发布模式旨在降低系统不同模块之间的耦合度。一个复杂的系统一般要划分为好多不同的类,这些对象之间并不独立,存在各种协作关系,这就需要维护对象之间的一致性,这给系统的维护、重用和扩展带来不便,严重限制了系统的灵活性。这样就可以把主动变化因素抽象出来形成发布者,而其他依赖者抽象为订阅者,使他们可以独立的被复用和维护。双发都只依赖与抽象,而不是依赖于具体实现。比如发布者新增一个订阅者时只需要发布者注册一下,订阅者新增依赖时,只需要将自己注册到新的发布者即可。
三、实例:
有一个天气预报系统,负责通知明天的天气情况。有几个角色订阅了该系统,他们根据明天的天气情况安排明天的事务。这几个角色分别为农夫、建筑工人、程序员。
下雨天
农夫喜出望外:又可以好好歇一天了,让庄稼庄稼好好成长吧;
建筑工人欣喜万分:完美,睡到天昏地暗;
程序员:继续上班,关我毛事;
日晴万里
农夫感慨:即将迎接充实的一天,收获满满;
建筑工人牢骚:这么大太阳,苦逼的一天;
程序员:继续上班,关我毛事;
使用Java语言具体实现过程:
1.发布者接口:
/*发布者接口,定义注册发布者,删除发布者,发布消息的接口*/ public interface IWeather { void addSubscriber(ISubscriber subscriber); void delSubscriber(ISubscriber subscriber); void publishInfo(String msg); } 复制代码
2.发布者具体实现
-
-
import org.apache.log4j.Logger;
-
-
import java.util.ArrayList;
-
import java.util.List;
-
-
/*发布者具体实现类*/
-
public class WeatherServer implements IWeather {
-
-
private static final Logger logger = Logger.getLogger(WeatherServer.class);
-
-
/*用来保存注册了的所有订阅者*/
-
private List<ISubscriber> subscribers = new ArrayList<ISubscriber>();
-
-
public void addSubscriber(ISubscriber subscriber) {
-
subscribers.add(subscriber);
-
logger.info(
"a new subscriber is joining");
-
}
-
-
public void delSubscriber(ISubscriber subscriber) {
-
subscribers.remove(subscriber);
-
logger.info(
"a subscriber is leaving");
-
}
-
-
public void publishInfo(String msg) {
-
for(ISubscriber subscriber : subscribers) subscriber.todoTomorrow(msg);
-
logger.info(String.format(
"publish a msg: %s ",msg));
-
}
-
}
-
-
复制代码
3.订阅者接口
/*订阅者接口,所有订阅WeatherServer 的订阅者都要实现该接口,定义了收到发布者消息之后做出反应的方法*/ public interface ISubscriber { void todoTomorrow(String msg); } 复制代码
4.具体订阅者实现
-
import org.apache.log4j.Logger;
-
public class Farmer implements ISubscriber{
-
private static final Logger logger = Logger.getLogger(Farmer.class);
-
-
public void todoTomorrow(String msg) {
-
-
if(
"rain".equals(msg)){
-
logger.info(
"FARMER : a wonderful day!!!");
-
}
else
if(
"sunny".equals(msg)){
-
logger.info(
"FARMER : a enrich day!!!");
-
}
else {
-
logger.info(
"FARMER : Spam messages");
-
}
-
}
-
}
-
-
-
public class Worker implements ISubscriber{
-
private static final Logger logger = Logger.getLogger(Farmer.class);
-
-
public void todoTomorrow(String msg) {
-
-
if(
"rain".equals(msg)){
-
logger.info(
"WORKER : a satisfied day!!!");
-
}
else
if(
"sunny".equals(msg)){
-
logger.info(
"WORKER : a terrible day!!!");
-
}
else {
-
logger.info(
"WORKER : Spam messages");
-
}
-
}
-
}
-
-
-
public class Programmer implements ISubscriber{
-
private static final Logger logger = Logger.getLogger(Farmer.class);
-
-
public void todoTomorrow(String msg) {
-
-
if(
"rain".equals(msg)){
-
logger.info(
"PROGRAMMER :raining??? Irrelevant !!!");
-
}
else
if(
"sunny".equals(msg)){
-
logger.info(
"PROGRAMMER : sunny Irrelevant !!!");
-
}
else {
-
logger.info(
"PROGRAMMER : Spam messages");
-
}
-
}
-
}
-
-
复制代码
5.测试类
-
*/
-
public class Boot {
-
-
-
public static void main(String[] args){
-
-
Farmer farmer = new Farmer();
-
Worker worker = new Worker();
-
Programmer programmer = new Programmer();
-
-
WeatherServer weatherServer = new WeatherServer();
-
-
weatherServer.addSubscriber(farmer);
-
weatherServer.addSubscriber(worker);
-
weatherServer.addSubscriber(programmer);
-
-
weatherServer.publishInfo(
"rain");
-
}
-
}
-
-
复制代码
6.运行结果:
有一个新的订阅者想要订阅天气预报的服务时,只需要调用weather的注册方法addSubscriber完成注册就能收到天气预报的信息。