设计模式之订阅/发布模式(subscribe/publish)

一、什么是订阅发布模式

订阅发布模式定义了一种 一对多 的依赖关系,一指发布者,比如某个主题对象,多指订阅者,依赖是订阅者对发布者的依赖;多个订阅者同时监听一个主题对象。当发布者即主题对象的状态发生变化时,会将该变化通知给订阅者,订阅者据此更新自己的状态。是设计模式中用的比较多的一种。

二、为什么使用订阅发布模式

订阅发布模式旨在降低系统不同模块之间的耦合度。一个复杂的系统一般要划分为好多不同的类,这些对象之间并不独立,存在各种协作关系,这就需要维护对象之间的一致性,这给系统的维护、重用和扩展带来不便,严重限制了系统的灵活性。这样就可以把主动变化因素抽象出来形成发布者,而其他依赖者抽象为订阅者,使他们可以独立的被复用和维护。双发都只依赖与抽象,而不是依赖于具体实现。比如发布者新增一个订阅者时只需要发布者注册一下,订阅者新增依赖时,只需要将自己注册到新的发布者即可。

三、实例:

有一个天气预报系统,负责通知明天的天气情况。有几个角色订阅了该系统,他们根据明天的天气情况安排明天的事务。这几个角色分别为农夫、建筑工人、程序员。

下雨天
农夫喜出望外:又可以好好歇一天了,让庄稼庄稼好好成长吧;
建筑工人欣喜万分:完美,睡到天昏地暗;
程序员:继续上班,关我毛事;

日晴万里
农夫感慨:即将迎接充实的一天,收获满满;
建筑工人牢骚:这么大太阳,苦逼的一天;
程序员:继续上班,关我毛事;

使用Java语言具体实现过程:

1.发布者接口:


    
    
  1. /*发布者接口,定义注册发布者,删除发布者,发布消息的接口*/
  2. public interface IWeather {
  3. void addSubscriber(ISubscriber subscriber);
  4. void delSubscriber(ISubscriber subscriber);
  5. void publishInfo(String msg);
  6. }
  7. 复制代码

2.发布者具体实现


    
    
  1. import org.apache.log4j.Logger;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. /*发布者具体实现类*/
  5. public class WeatherServer implements IWeather {
  6. private static final Logger logger = Logger.getLogger(WeatherServer.class);
  7. /*用来保存注册了的所有订阅者*/
  8. private List<ISubscriber> subscribers = new ArrayList<ISubscriber>();
  9. public void addSubscriber(ISubscriber subscriber) {
  10. subscribers.add(subscriber);
  11. logger.info( "a new subscriber is joining");
  12. }
  13. public void delSubscriber(ISubscriber subscriber) {
  14. subscribers.remove(subscriber);
  15. logger.info( "a subscriber is leaving");
  16. }
  17. public void publishInfo(String msg) {
  18. for(ISubscriber subscriber : subscribers) subscriber.todoTomorrow(msg);
  19. logger.info(String.format( "publish a msg: %s ",msg));
  20. }
  21. }
  22. 复制代码

3.订阅者接口


    
    
  1. /*订阅者接口,所有订阅WeatherServer 的订阅者都要实现该接口,定义了收到发布者消息之后做出反应的方法*/
  2. public interface ISubscriber {
  3. void todoTomorrow(String msg);
  4. }
  5. 复制代码

4.具体订阅者实现


    
    
  1. import org.apache.log4j.Logger;
  2. public class Farmer implements ISubscriber{
  3. private static final Logger logger = Logger.getLogger(Farmer.class);
  4. public void todoTomorrow(String msg) {
  5. if( "rain".equals(msg)){
  6. logger.info( "FARMER : a wonderful day!!!");
  7. } else if( "sunny".equals(msg)){
  8. logger.info( "FARMER : a enrich day!!!");
  9. } else {
  10. logger.info( "FARMER : Spam messages");
  11. }
  12. }
  13. }
  14. public class Worker implements ISubscriber{
  15. private static final Logger logger = Logger.getLogger(Farmer.class);
  16. public void todoTomorrow(String msg) {
  17. if( "rain".equals(msg)){
  18. logger.info( "WORKER : a satisfied day!!!");
  19. } else if( "sunny".equals(msg)){
  20. logger.info( "WORKER : a terrible day!!!");
  21. } else {
  22. logger.info( "WORKER : Spam messages");
  23. }
  24. }
  25. }
  26. public class Programmer implements ISubscriber{
  27. private static final Logger logger = Logger.getLogger(Farmer.class);
  28. public void todoTomorrow(String msg) {
  29. if( "rain".equals(msg)){
  30. logger.info( "PROGRAMMER :raining??? Irrelevant !!!");
  31. } else if( "sunny".equals(msg)){
  32. logger.info( "PROGRAMMER : sunny Irrelevant !!!");
  33. } else {
  34. logger.info( "PROGRAMMER : Spam messages");
  35. }
  36. }
  37. }
  38. 复制代码

5.测试类


    
    
  1. */
  2. public class Boot {
  3. public static void main(String[] args){
  4. Farmer farmer = new Farmer();
  5. Worker worker = new Worker();
  6. Programmer programmer = new Programmer();
  7. WeatherServer weatherServer = new WeatherServer();
  8. weatherServer.addSubscriber(farmer);
  9. weatherServer.addSubscriber(worker);
  10. weatherServer.addSubscriber(programmer);
  11. weatherServer.publishInfo( "rain");
  12. }
  13. }
  14. 复制代码

6.运行结果:

有一个新的订阅者想要订阅天气预报的服务时,只需要调用weather的注册方法addSubscriber完成注册就能收到天气预报的信息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值