zoukankan      html  css  js  c++  java
  • 设计模式-观察者模式

    观察者模式:

    当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。具体如以下案例:

    一、使用原生方法

    1.com.cyb包下建立springboot启动类:

    1 @SpringBootApplication
    2 public class AppObServer {
    3     public static void main(String[] args) {
    4         SpringApplication.run(AppObServer.class);
    5     }
    6 }

    2.com.cyb.observice包下建立观察者接口

    1 /**
    2  *  @author: cyb
    3  *  @Date: 2020-05-24 11:29
    4  *  @Description:观察者接口
    5  */
    6 public interface ObServer {
    7 
    8     void sendMsg(JSONObject jsonObject);
    9 }

    3.com.cyb.observer.impl包下建立观察者实行类

     1 /**
     2  *  @author: cyb
     3  *  @Date: 2020-05-24 11:28
     4  *  @Description:邮件观察者
     5  */
     6 @Component
     7 @Slf4j
     8 public class EmailObServer implements ObServer {
     9     @Override
    10     public void sendMsg(JSONObject jsonObject) {
    11         log.info("使用观察者发送邮件");
    12     }
    13 }
    14 /**
    15  *  @author: cyb
    16  *  @Date: 2020-05-24 11:28
    17  *  @Description:短信观察者
    18  */
    19 @Component
    20 @Slf4j
    21 public class SMSObServer implements ObServer {
    22     @Override
    23     public void sendMsg(JSONObject jsonObject) {
    24         log.info("使用观察者发送短信");
    25     }
    26 }

    4.com.cyb.observer包下建立观察者主题类,供调用

     1 /**
     2  *  @author: cyb
     3  *  @Date: 2020-05-24 11:28
     4  *  @Description:自定义观察者主题
     5  */
     6 @Component
     7 public class CybSubject {
     8 
     9     /**
    10      * 类型 ObServer
    11      */
    12     private List<ObServer> listObServer = new ArrayList<>();
    13     /**
    14      * 线程池
    15      */
    16     private ExecutorService executorService;
    17 
    18 
    19     public CybSubject() {
    20         executorService = Executors.newFixedThreadPool(10);
    21     }
    22 
    23     /**
    24      * 新增ObServer
    25      *
    26      * @param obServer
    27      */
    28     public void addObServer(ObServer obServer) {
    29         listObServer.add(obServer);
    30     }
    31 
    32     /**
    33      * 通知给所有的观察者
    34      *每分发一个观察者就开启一个线程
    35      * @param jsonObject
    36      */
    37     public void notifyObServer(JSONObject jsonObject) {
    38         for (ObServer obServer :
    39                 listObServer) {
    40             // 单独开启线程异步通知
    41             executorService.execute(new Runnable() {
    42                 @Override
    43                 public void run() {
    44                     obServer.sendMsg(jsonObject);
    45                 }
    46             });
    47         }
    48     }

    5.com.cyb.start包下建立项目启动成功后自动执行方法

     1 /**
     2  *  @author: cyb
     3  *  @Date: 2020-05-24 11:30
     4  *  @Description:设置项目启动成功后自动加载类,把SMSObServer和EmailObServer等对象放置该类启动的原因是防止在调用时由于加载问题,
     5  *  执行时还未加载,特放此避免该问题的发生,但是在添加是使用了动态添加,我们不需要手动注入对象,具体如下代码
     6  *   Map<String, ObServer> map = applicationContext.getBeansOfType(ObServer.class);
     7  */
     8 @Component
     9 public class StartService implements ApplicationRunner, ApplicationContextAware {
    10     /***
    11      * 被:Map<String, ObServer> map = applicationContext.getBeansOfType(ObServer.class);方法替代
    12      */
    13     @Autowired
    14     private SMSObServer smsObServer;
    15     /***
    16      * 被:Map<String, ObServer> map = applicationContext.getBeansOfType(ObServer.class);方法替代
    17      */
    18     @Autowired
    19     private EmailObServer emailObServer;
    20     @Autowired
    21     private CybSubject cybSubject;
    22 
    23 
    24     private ApplicationContext applicationContext;
    25 
    26     /**
    27      * 当我们的SpringBoot启动成功的时候,注册我们的SMSObServer
    28      * 皮卡丘
    29      *
    30      * @param args
    31      * @throws Exception
    32      */
    33     @Override
    34     public void run(ApplicationArguments args) throws Exception {
    35         /**
    36          * 自动注册我们观察者
    37          *
    38          * 1.使用Spring获取该ObServer下有那些bean对象
    39          * 2.直接注添加到集合中
    40          *
    41          */
    42         //根据接口类型返回相应的所有bean
    43         Map<String, ObServer> map = applicationContext.getBeansOfType(ObServer.class);
    44         for (String key : map.keySet()) {
    45             ObServer obServer = map.get(key);
    46             cybSubject.addObServer(obServer);
    47         }
    48     }
    49 
    50     @Override
    51     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    52         this.applicationContext = applicationContext;
    53     }
    54 }

    二、使用spring提供的观察者模式: 

    1、com.cyb.utils包下建立spring工具类

     1 /**
     2  * SpringUtils 工具类
     3  */
     4 @Component
     5 public class SpringUtils implements ApplicationContextAware {
     6 
     7 
     8     private static ApplicationContext applicationContext = null;
     9 
    10     public static ApplicationContext getApplicationContext() {
    11         return applicationContext;
    12     }
    13 
    14 
    15     public static <T> T getBean(String beanId) {
    16         return (T) applicationContext.getBean(beanId);
    17     }
    18 
    19     public static <T> T getBean(Class<T> requiredType) {
    20         return (T) applicationContext.getBean(requiredType);
    21     }
    22 
    23 
    24     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    25         SpringUtils.applicationContext = applicationContext;
    26     }
    27 
    28 }


    2、
    com.cyb.entity包下建立实体

     1 /*
     2 使用spring观察者,需要继承ApplicationEvent
     3  */
     4 public class UserMessageEntity extends ApplicationEvent {
     5     private String email;
     6     private String phone;
     7     private String userId;
     8 
     9     /**
    10      * Create a new ApplicationEvent.
    11      *
    12      * @param source the object on which the event initially occurred (never {@code null})
    13      */
    14     public UserMessageEntity(Object source) {
    15         super(source);
    16     }
    17 
    18     public UserMessageEntity(Object source, String email, String phone) {
    19         super(source);
    20         this.email = email;
    21         this.phone = phone;
    22     }
    23 
    24     @Override
    25     public String toString() {
    26         return "email:" + email + ",phone:" + phone;
    27     }
    28 }

    3、com.cyb.listener包下建立对应的观察者对象

     1 /**
     2  *  @author: cyb
     3  *  @Date: 2020-05-24 11:26
     4  *  @Description:使用spring观察者-邮件监听
     5  */
     6 @Component
     7 public class EmailListener implements ApplicationListener<UserMessageEntity> {
     8     /**
     9      * 监听的方法
    10      *
    11      * @param event
    12      */
    13     @Override
    14     @Async
    15     public void onApplicationEvent(UserMessageEntity event) {
    16         System.out.println(Thread.currentThread().getName()+"邮件:" + event.toString());
    17     }
    18 }
    19 /**
    20  *  @author: cyb
    21  *  @Date: 2020-05-24 11:27
    22  *  @Description:使用spring观察者-短信监听
    23  */
    24 @Component
    25 public class SmSListener implements ApplicationListener<UserMessageEntity> {
    26     /**
    27      * 监听的方法
    28      *
    29      * @param event
    30      */
    31     @Override
    32     public void onApplicationEvent(UserMessageEntity event) {
    33         System.out.println("短信:" + event.toString());
    34     }
    35 }


    com.cyb.service包下建立控制层

    /**
     *  @author: cyb
     *  @Date: 2020-05-24 11:29
     *  @Description:接口层
     */
    @RestController
    @Slf4j
    public class OrderService {
    
    
        @Autowired
        private CybSubject cybSubject;
        @Autowired
        private ApplicationEventPublisher applicationEventPublisher;
        @RequestMapping("/addOrder")
        public String addOrder() {
            log.info("1.调用数据库下单订单代码:");
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("sms", "1865891111");
            jsonObject.put("email", "963859193@qq.com");
            cybSubject.notifyObServer(jsonObject);
            return "success";
        }
    
        @RequestMapping("/addOrder2")
        public String addOrder2() {
            log.info("1.调用数据库下单订单代码:");
            UserMessageEntity userMessageEntity = new UserMessageEntity(
                    this, "963859193@qq.com", "1865891111");
            applicationEventPublisher.publishEvent(userMessageEntity);
            return "success";
        }
    }

    以上则为观察模式的两种写法,该以上内容参照于余胜军,对其感兴趣的请点击链接进行了解,转发该篇博客时请大家说明出处。

    技术在于沟通!

  • 相关阅读:
    继承与多态
    本周总结
    总结
    周总结
    周总结
    第三周总结
    .......
    .....
    ....
    ....
  • 原文地址:https://www.cnblogs.com/chenyuanbo/p/12953156.html
Copyright © 2011-2022 走看看