设计模式-6-观察者
简介:被观察者管理着观察者,当被观察者发生变化,主动向观察者发出通知
目的:建立对象之间的依赖关系, 对象发生改变自动通知其他对象,其他对象作出相应的反应
总结:订阅-发布模式
组成: 观察者, 被观察者
实现方式: 1-自定义 2-JDK
一, 自定义方式
1,观察者
package com.design.f.observer.base; /** * 观察者接口 */ public interface ObserverService { /** * 被观察者发生改变需要观察者执行的动作 */ Boolean update(); }
package com.design.f.observer.base; /** * 观察者A */ public class ObserverAServiceImpl implements ObserverService { @Override public Boolean update() { System.out.println("收到被观察者的变化 --> 观察者A --> 相应的处理 "); return true; } }
package com.design.f.observer.base; /** * 观察者B */ public class ObserverBServiceImpl implements ObserverService { @Override public Boolean update() { System.out.println("收到被观察者的变化 --> 观察者B --> 相应的处理 "); return true; } }
2,被观察者
package com.design.f.observer.base; import java.util.ArrayList; import java.util.List; /** * 被观察者 */ public class Observable { //1-记录观察者 private List<ObserverService> observers = new ArrayList<ObserverService>(); public Boolean addObserver(ObserverService observerService){ return observers.add(observerService); } //2-发生改变的动作 public void changed(){ System.out.println("被观察者已发生变化 ... ... "); notifyObserver(); } //3-通知观察者 private void notifyObserver(){ System.out.println("被观察者开始通知观察者 ... ... "); for(ObserverService observerService : observers){ observerService.update(); } } }
3,Main
package com.design.f.observer.base; /** * 6-观察者模式 * 简介:一个对象状态的改变需要通知很多对这个对象关注的一系列对象,就可以使用观察者模式。 * 用例:文件上传的进度显示,被关注的博主发布新文章通知关注着,小说网站的订阅者在发布新的小说后通知订阅者 * * 事件驱动模型 * 观察者更多的强调的是发布-订阅式的问题处理,而事件驱动则更多的注重于界面与数据模型之间的问题 * 被观察者 = 事件源 * 观察者 = 监听器 * * 用例:Tomcat的启动用到的listener监听器,Spring启动添加监听器随着Tomcat的启动IOC容器也开始启动 */ public class MainTest { public static void main(String[] args) { /** * 观察者模式-自定义 */ //1-创建观察者 ObserverService observerA = new ObserverAServiceImpl(); ObserverService observerB = new ObserverBServiceImpl(); //2-向被观察者添加观察者 Observable observed = new Observable(); observed.addObserver(observerA); observed.addObserver(observerB); //3-触发被观察者发生改变,通知观察者 observed.changed(); } }
4,Result
被观察者已发生变化 ... ... 被观察者开始通知观察者 ... ... 收到被观察者的变化 --> 观察者A --> 相应的处理 收到被观察者的变化 --> 观察者B --> 相应的处理
二,JDK实现方式
1,基础用户类
package com.design.f.observer.base; import java.io.Serializable; /** * 用户 */ public class User implements Serializable{ private static final long serialVersionUID = 158957714520271405L; private String userName; public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } @Override public String toString() { return super.toString(); } }
2,观察者
package com.design.f.observer.base; import java.util.Observable; import java.util.Observer; /** * 观察者 */ public class Reader implements Observer { //读者用户信息 private User user; public Reader(String userName){ user = new User(); user.setUserName(userName); } //关注作者 public void subscriptionWriter(String writerName){ //检查作者是否存在 if(WriterManager.getInstance().isWriter(writerName)){ WriterManager.getInstance().getWriter(writerName).addObserver(this); } } //取消关注 public void unSubscriptionWriter(String writerName){ //检查作者是否存在 if(WriterManager.getInstance().isWriter(writerName)){ WriterManager.getInstance().getWriter(writerName).deleteObserver(this); } } //收到被观察者的要执行的动作 @Override public void update(Observable o, Object arg) { if(o instanceof Writer){ Writer writer = (Writer) o; System.out.println("读者 : " + user.getUserName() + " 收到作者: " + writer.getUser().getUserName() + " 发布的新书: " +writer.getLastBook()); } } public User getUser() { return user; } public void setUser(User user) { this.user = user; } }
3,被观察者
package com.design.f.observer.base; import java.util.Observable; /** * 被观察者 */ public class Writer extends Observable { //作者用户信息 private User user; //作者新书 private String lastBook; public Writer(String userName){ //初始化用户信息 user = new User(); user.setUserName(userName); //将作者添加到作者管理器中 WriterManager.getInstance().addWriter(this); } //作者发布新书动作 public void pushBook(String bookName){ System.out.println("作者 : " + user.getUserName() + "; 发布了新书: " + bookName + " ... ... "); lastBook = bookName; //设置被观察发生改变的状态,并通知观察者 setChanged(); notifyObservers(); } public String getLastBook() { return lastBook; } public void setLastBook(String lastBook) { this.lastBook = lastBook; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } }
4,观察者管理器
package com.design.f.observer.base; import java.util.HashMap; import java.util.Map; /** * 观察者管理器 */ public class WriterManager { //1-作者集合 private Map<String, Writer> writerMap = new HashMap<String, Writer>(); //2-添加作者 public void addWriter(Writer writer){ writerMap.put(writer.getUser().getUserName(), writer); } //3-删除作者 public void removeWriter(Writer writer){ writerMap.remove(writer.getUser().getUserName()); } //4-获取作者 public Writer getWriter(String writerName){ return writerMap.get(writerName); } //5-作者是否存在 public Boolean isWriter(String writerName){ return writerMap.containsKey(writerName); } //获取作者集合单例 private WriterManager(){} public static WriterManager getInstance(){ return WriterManagerInstance.writerManager; } private static class WriterManagerInstance{ static WriterManager writerManager = new WriterManager(); } public Map<String, Writer> getWriterMap() { return writerMap; } public void setWriterMap(Map<String, Writer> writerMap) { this.writerMap = writerMap; } }
5,Main
package com.design.f.observer.base; /** * 6-观察者模式 * 简介:一个对象状态的改变需要通知很多对这个对象关注的一系列对象,就可以使用观察者模式。 * 用例:文件上传的进度显示,被关注的博主发布新文章通知关注着,小说网站的订阅者在发布新的小说后通知订阅者 * * 事件驱动模型 * 观察者更多的强调的是发布-订阅式的问题处理,而事件驱动则更多的注重于界面与数据模型之间的问题 * 被观察者 = 事件源 * 观察者 = 监听器 * * 用例:Tomcat的启动用到的listener监听器,Spring启动添加监听器随着Tomcat的启动IOC容器也开始启动 */ public class MainTest { public static void main(String[] args) { /** * 观察者模式-自定义 */ // //1-创建观察者 // ObserverService observerA = new ObserverAServiceImpl(); // ObserverService observerB = new ObserverBServiceImpl(); // //2-向被观察者添加观察者 // Observable observed = new Observable(); // observed.addObserver(observerA); // observed.addObserver(observerB); // //3-触发被观察者发生改变,通知观察者 // observed.changed(); /** * 观察者模式-JDK */ //1-创建读者 Reader readerA = new Reader("读者A"); Reader readerB = new Reader("读者B"); Reader readerC = new Reader("读者C"); Reader readerD = new Reader("读者D"); //2-创建作者 Writer writerA = new Writer("莫言"); Writer writerB = new Writer("路遥"); //3-将读者关注到作者 readerA.subscriptionWriter("莫言"); readerB.subscriptionWriter("莫言"); readerC.subscriptionWriter("莫言"); readerD.subscriptionWriter("莫言"); readerA.subscriptionWriter("路遥"); readerB.subscriptionWriter("路遥"); //5-作者发布新书 writerA.pushBook("平凡的世界"); writerB.pushBook("悲惨的世界"); //6-读者A取消路遥关注 readerA.unSubscriptionWriter("路遥"); writerB.pushBook("十月围城"); } }
6,Result
作者 : 莫言; 发布了新书: 平凡的世界 ... ...
读者 : 读者D 收到作者: 莫言 发布的新书: 平凡的世界
读者 : 读者C 收到作者: 莫言 发布的新书: 平凡的世界
读者 : 读者B 收到作者: 莫言 发布的新书: 平凡的世界
读者 : 读者A 收到作者: 莫言 发布的新书: 平凡的世界
作者 : 路遥; 发布了新书: 悲惨的世界 ... ...
读者 : 读者B 收到作者: 路遥 发布的新书: 悲惨的世界
读者 : 读者A 收到作者: 路遥 发布的新书: 悲惨的世界
作者 : 路遥; 发布了新书: 十月围城 ... ...
读者 : 读者B 收到作者: 路遥 发布的新书: 十月围城