设计模式-观察者模式
观察者模式:
当对象间存在一对多关系时,则使用观察者模式(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"; } }
以上则为观察模式的两种写法,该以上内容参照于余胜军,对其感兴趣的请点击链接进行了解,转发该篇博客时请大家说明出处。
技术在于沟通!