设计模式-观察者模式

 

观察者模式:

当对象间存在一对多关系时,则使用观察者模式(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";
    }
}

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

技术在于沟通!

posted @ 2020-05-24 22:40  陈远波  阅读(215)  评论(0编辑  收藏  举报