设计模式之观察者模式(Observer)
其实我以前也有学习过设计模式,也写过一些代码。这次在看代码时,发现设计模式使用的泛滥,想想我的设计模式学习的不够扎实,所以重新拾起,把以前没有学习的设计模式学习一遍,把学习过的设计模式在重温一遍。第一篇我选择的是观察者模式。我在项目代码中看到这个模式,项目中的使用大概说一下:服务器与客户端的交互,服务器端的代码使用了观察者模式,作用是:当用户发送请求以后,通过注册的Manager管理类来调用相应的方法处理用户的请求。
这里做一个报社新闻给用户推送新闻的案例(当报社推送新闻的时候,所有订阅了报社的读者可以阅读报纸):
方案一:采用Java自带的观察者接口实现,如下:
首先是报社类,继承了Observable,需要注意的是在通知观察者之前需要setChanged一下,因为notifyObservers()在调用时,需要知道自己的观察者发生了改变,而这个方法是通过Changed变量来判断是否为true,如果不为true,直接return,具体可以查看源码。所以我们需要setChanged,让hasChanged方法返回true。具体可以看notifyObservers()的定义说明
import java.util.Observable; public class Publisher extends Observable { public void updateNews(String str) { setChanged(); notifyObservers(str); } }
然后是用户读者:(这里做了2个读者)需要实现Observer接口,并实现接口内部的具体方法update().实现这样的update方法,主要是因为在notifyObservers函数中对这个update方法进行了调用。这也是设计模式的精髓所在。我们可以查看Observable的具体实现,从而知道如何设计一个抽象的观察者。
import java.util.Observable; import java.util.Observer; public class Reader_1 implements Observer{ @Override public void update(Observable o, Object arg) { // TODO Auto-generated method stub if(arg instanceof String){ System.out.println("I'm Reader_1,"+(String)arg); } } }
import java.util.Observable; import java.util.Observer; public class Reader_2 implements Observer{ @Override public void update(Observable o, Object arg) { // TODO Auto-generated method stub if(arg instanceof String){ System.out.println("I'm Reader_2,"+(String)arg); } } }
然后是我们的测试Main类:需要做的是创建出版社,读者1,读者2。
读者1,读者2都订阅报社的报纸。第一次推送。
然后读者1退订报纸,报社第二次推送。
public class Main { public static void main(String[] args) { Publisher p = new Publisher(); Reader_1 r1 = new Reader_1(); Reader_2 r2 = new Reader_2(); p.addObserver(r1); p.addObserver(r2); System.out.println("当前读者数:"+p.countObservers()); System.out.println("第一次推送消息:"); p.updateNews("CCTV-5 SportNews"); p.deleteObserver(r1); System.out.println("\n当前读者数:"+p.countObservers()); System.out.println("第二次推送消息:"); p.updateNews("News for Car"); } }
运行结果:
当前读者数:2 第一次推送消息: I'm Reader_2,CCTV-5 SportNews I'm Reader_1,CCTV-5 SportNews 当前读者数:1 第二次推送消息: I'm Reader_2,News for Car
==============================================================================================================================
方案二:自己动手,丰衣足食。我们需要实现的是抽象报社,抽象读者,具体报社,具体读者,外加一个测试函数即可,
其实跟Java自己实现的观察者接口相差并不多,下面就简单的实现它的基础功能,如下所示:
思路清晰,写代码:
package demo; import java.util.Vector; public class AbstractPublisher { // 库函数采用的是Vector来实现对注册读者的存储,我们也走大神的路 Vector<AbstractReader> vector; public AbstractPublisher() { vector = new Vector<AbstractReader>(); } public boolean addReader(AbstractReader ar) { if (vector.add(ar)) return true; return false; } public boolean deleteReader(AbstractReader ar) { if (vector.remove(ar)) return true; return false; } public void notifyReaders(String news) { for (AbstractReader ar : vector) { ar.readNews(news); } } }
package demo; public interface AbstractReader { public void readNews(String news); }
package demo; public class Publisher extends AbstractPublisher { //推送新闻给读者 public void pushNews(String news) { notifyReaders(news); } }
package demo; public class Reader_Joy implements AbstractReader{ @Override public void readNews(String news) { // TODO Auto-generated method stub System.out.println("I'm Reader_Joy " + news); } }
package demo; public class Reader_Tom implements AbstractReader{ @Override public void readNews(String news) { // TODO Auto-generated method stub System.out.println("I'm Reader_Tom "+news); } }
package demo; public class Main { public static void main(String[] args) { Publisher p = new Publisher(); Reader_Joy joy = new Reader_Joy(); Reader_Tom tom = new Reader_Tom(); p.addReader(joy); p.addReader(tom); System.out.println("第一次推送消息:"); p.pushNews("News Of Game"); p.deleteReader(joy); System.out.println("第二次推送消息:"); p.pushNews("News Of City"); } }
运行结果:
第一次推送消息: I'm Reader_Joy News Of Game I'm Reader_Tom News Of Game 第二次推送消息: I'm Reader_Tom News Of City
基本的代码实现就是这样,也许还有错误,但是观察者的基本思想就此理清楚了。
核心部分:1)报社如何存储注册的读者
2)报社如何通知注册的读者
3)如何使用接口和继承的方式组织结构。
项目源代码:http://www.kuaipan.cn/file/id_132802506211221411.htm?source=1