Java设计模式——观察者模式
2016-05-20 17:38
477 查看
不知道大家有没有注意到,生活中有很多时候,发生事件A就会触发事件B。
还记得上学的时候吗,每当在课堂上偷偷睡觉的时候,总是会让同桌在老师过来的时候叫醒自己。这实际上就是同桌充当了“观察者”,而你充当了“订阅者”的角色,一旦“老师来了”这件事情发生,你的同桌就会“向你发送消息”通知你老师来了。这实际上就是一套“观察者模式的流程”
观察者模式定义了对象间的一种一对多依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。
下面以一个小程序来举例子
假如我们要做一个订报的小程序,每当报社发布了一本新书,读者就会收到新书消息的通知。
经过一番思考之后,决定这样设计:定义一个读者类和报社类。
报社类需要有订阅读者的列表,添加或者移除读者的方法,通知所有订阅者的方法,更新书本信息的方法。
读者类中需要有接受报社传递的信息的方法。
然后写出了如下代码:
输出结果如下:
我是读者读者一很高兴收到了大毛*第一本书
我是读者读者二很高兴收到了大毛*第一本书
我是读者读者一很高兴收到了二毛*第二本书
我是读者读者二很高兴收到了二毛*第二本书
我是读者读者一很高兴收到了三毛*第三本书
我是读者读者二很高兴收到了三毛*第三本书
这时候看起来似乎结果还是很满意的,符合系统设计的预期。
但是不知道大家有没有发现,这是针对实现变成而不是针对接口编程。
如果添加了新的类型的读者,报社需要增加新的代码来适配新的读者。
这时候可以使用今天要介绍的”观察者模式“来实现
关于观察者的一切,主题只需要知道观察者实现了观察者接口,主题不需要知道观察者的具体实现。任何时候我们都可以增加或者删除观察者,主题不会受到任何影响。
有新的类型的观察者出现时,主题不需要任何的修改,只要观察者实现了观察者接口,即可注册成为观察者。主题和观察者这种松耦合的设计,可以应对各种场合。
首先创建观察者和主题。
创建报社类实现主题接口
测试类如下
输出结果:
我是读者读者一很高兴收到了大毛*第一本书
我是读者读者二很高兴收到了大毛*第一本书
我是读者读者一很高兴收到了二毛*第二本书
我是读者读者二很高兴收到了二毛*第二本书
我是读者读者一很高兴收到了三毛*第三本书
我是读者读者二很高兴收到了三毛*第三本书
以上。
如有不对请指出。
还记得上学的时候吗,每当在课堂上偷偷睡觉的时候,总是会让同桌在老师过来的时候叫醒自己。这实际上就是同桌充当了“观察者”,而你充当了“订阅者”的角色,一旦“老师来了”这件事情发生,你的同桌就会“向你发送消息”通知你老师来了。这实际上就是一套“观察者模式的流程”
观察者模式定义了对象间的一种一对多依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。
下面以一个小程序来举例子
假如我们要做一个订报的小程序,每当报社发布了一本新书,读者就会收到新书消息的通知。
经过一番思考之后,决定这样设计:定义一个读者类和报社类。
报社类需要有订阅读者的列表,添加或者移除读者的方法,通知所有订阅者的方法,更新书本信息的方法。
读者类中需要有接受报社传递的信息的方法。
然后写出了如下代码:
public class NewsOffice { //报社类 List<Reader> readers; public String bookname; public String writer; public NewsOffice() { readers = new ArrayList<>(); } //注册读者 public void addReader(Reader reader) { readers.add(reader); } //移除读者 public void removeReader(Reader reader){ int index=readers.indexOf(reader); if (index>0) { readers.remove(index); } } //通知所有注册的读者有新书了 public void notifyAllObserver(){ for(Reader reader:readers){ reader.update(writer+"***"+bookname); } } //设置新书的信息 public void setInformation(String bookname,String writer){ this.bookname=bookname; this.writer=writer; notifyAllObserver(); } }
public class Reader { String readername; String bookinformation; public Reader(String readername) { this.readername = readername; } public void update(String bookinformation) { this.bookinformation=bookinformation; display(); } private void display() { System.out.print("我是读者"+readername+"很高兴收到了"); System.out.println(bookinformation); } }
public class Test { public static void main(String[] a) { NewsOffice newsOffic = new NewsOffice(); Reader reader1 = new Reader("读者一"); Reader reader2 = new Reader("读者二"); newsOffic.addReader(reader1); newsOffic.addReader(reader2); newsOffic.setInformation("第一本书", "大毛"); newsOffic.setInformation("第二本书", "二毛"); newsOffic.setInformation("第三本书", "三毛"); } }
输出结果如下:
我是读者读者一很高兴收到了大毛*第一本书
我是读者读者二很高兴收到了大毛*第一本书
我是读者读者一很高兴收到了二毛*第二本书
我是读者读者二很高兴收到了二毛*第二本书
我是读者读者一很高兴收到了三毛*第三本书
我是读者读者二很高兴收到了三毛*第三本书
这时候看起来似乎结果还是很满意的,符合系统设计的预期。
但是不知道大家有没有发现,这是针对实现变成而不是针对接口编程。
如果添加了新的类型的读者,报社需要增加新的代码来适配新的读者。
这时候可以使用今天要介绍的”观察者模式“来实现
关于观察者的一切,主题只需要知道观察者实现了观察者接口,主题不需要知道观察者的具体实现。任何时候我们都可以增加或者删除观察者,主题不会受到任何影响。
有新的类型的观察者出现时,主题不需要任何的修改,只要观察者实现了观察者接口,即可注册成为观察者。主题和观察者这种松耦合的设计,可以应对各种场合。
首先创建观察者和主题。
public interface Observer { //使用Update方法接收传递的书本信息 public void update(String bookname); }
public interface Supervisor { //增加观察者 public void addObserver(Observer observer); //移除观察者 public void removeObserver(Observer observer); //通知所有观察者 public void notifyAllObserver(); }
创建报社类实现主题接口
public class NewsOffice implements Supervisor { public List<Observer> observers; public String bookname; public String writer; public NewsOffice() { observers=new ArrayList<Observer>(); } @Override public void addObserver(Observer observer) { observers.add(observer); } @Override public void removeObserver(Observer observer) { int i=observers.indexOf(observer); if (i>0) { observers.remove(i); } } @Override public void notifyAllObserver() { //遍历所有的观察者发送消息 for(Observer observer:observers){ observer.update(writer+"***"+bookname); } } public void setInformation(String bookname,String writer){ //更新书本的信息,并且将更新的信息通过notifyAllObserver传递给观察者 this.bookname=bookname; this.writer=writer; notifyAllObserver(); } }
public class Reader implements Observer { private String bookinformation; private String readername; public Reader(String readername) { this.readername = readername; } @Override public void update(String bookinformation) { this.bookinformation = bookinformation; display(); } private void display() { System.out.print("我是读者"+readername+"很高兴收到了"); System.out.println(bookinformation); } }
测试类如下
public class Test { public static void main(String[] a) { NewsOffice newsOffic = new NewsOffice(); Reader reader1 = new Reader("读者一"); Reader reader2 = new Reader("读者二"); newsOffic.addObserver(reader1); newsOffic.addObserver(reader2); newsOffic.setInformation("第一本书", "大毛"); newsOffic.setInformation("第二本书", "二毛"); newsOffic.setInformation("第三本书", "三毛"); } }
输出结果:
我是读者读者一很高兴收到了大毛*第一本书
我是读者读者二很高兴收到了大毛*第一本书
我是读者读者一很高兴收到了二毛*第二本书
我是读者读者二很高兴收到了二毛*第二本书
我是读者读者一很高兴收到了三毛*第三本书
我是读者读者二很高兴收到了三毛*第三本书
以上。
如有不对请指出。
相关文章推荐
- Spring7:基于注解的Spring MVC(下篇)
- Java7中的ForkJoin并发框架初探(上)——需求背景和设计原理
- Spring6:基于注解的Spring MVC(上篇)
- Spring5:@Autowired注解、@Resource注解和@Service注解
- Spring4:JDBC
- Spring3:AOP
- Spring2:bean的使用
- Spring1:Spring简介、环境搭建、源码下载及导入MyEclipse
- Java之抽象类
- java之二分法递归显示数列
- Java main方法参数args[]
- Java三大特性之多态
- 深入Java集合学习系列:ArrayList的实现原理
- SSM框架——详细整合教程(Spring+SpringMVC+MyBatis)
- 离散FFT和图像二维FFT变换的java实现
- 深入Java集合学习系列:LinkedHashMap的实现原理
- Java开发使用Excel批量导入数据
- 深入Java集合学习系列:LinkedHashSet的实现原理
- 搭建JavaWeb服务器
- 深入Java集合学习系列:HashSet的实现原理