private static WriterManager instance = new WriterManager();
}
}
好了,这下我们的观察者模式就做好了,这个简单的DEMO可以支持读者关注作者,当作者发布新书时,读者会观察到这个事情,会产生相应的动作。下面我们写个客户端调用一下。
[java]
//客户端调用
public class Client {
public static void main(String[] args) {
//假设四个读者,两个作者
Reader r1 = new Reader("谢广坤");
Reader r2 = new Reader("赵四");
Reader r3 = new Reader("七哥");
Reader r4 = new Reader("刘能");
Writer w1 = new Writer("谢大脚");
Writer w2 = new Writer("王小蒙");
//四人关注了谢大脚
r1.subscribe("谢大脚");
r2.subscribe("谢大脚");
r3.subscribe("谢大脚");
r4.subscribe("谢大脚");
//七哥和刘能还关注了王小蒙
r3.subscribe("王小蒙");
r4.subscribe("王小蒙");
//作者发布新书就会通知关注的读者
//谢大脚写了设计模式
w1.addNovel("设计模式");
//王小蒙写了JAVA编程思想
w2.addNovel("JAVA编程思想");
//谢广坤取消关注谢大脚
r1.unsubscribe("谢大脚");
//谢大脚再写书将不会通知谢广坤
w1.addNovel("观察者模式");
}
}
//客户端调用
public class Client {
public static void main(String[] args) {
//假设四个读者,两个作者
Reader r1 = new Reader("谢广坤");
Reader r2 = new Reader("赵四");
Reader r3 = new Reader("七哥");
Reader r4 = new Reader("刘能");
Writer w1 = new Writer("谢大脚");
Writer w2 = new Writer("王小蒙");
//四人关注了谢大脚
r1.subscribe("谢大脚");
r2.subscribe("谢大脚");
r3.subscribe("谢大脚");
r4.subscribe("谢大脚");
//七哥和刘能还关注了王小蒙
r3.subscribe("王小蒙");
r4.subscribe("王小蒙");
//作者发布新书就会通知关注的读者
//谢大脚写了设计模式
w1.addNovel("设计模式");
//王小蒙写了JAVA编程思想
w2.addNovel("JAVA编程思想");
//谢广坤取消关注谢大脚
r1.unsubscribe("谢大脚");
//谢大脚再写书将不会通知谢广坤br /> w1.addNovel("观察者模式");
}
}
看下我们得到的结果,就会发现,我们确实通知了读者它所关注的作者的动态,而且读者取消关注以后,作者的动态将不再通知该读者。下面是运行结果。
我们使用观察者模式的用意是为了作者不再需要关心他发布新书时都要去通知谁,更重要的是他不需要关心他通知的是读者还是其它什么人,他只知道这个人是实现了观察者接口的,即我们的被观察者依赖的只是一个抽象的接口观察者接口,而不关心具体的观察者都有谁都是什么,比如以后要是游客也可以关注作者了,那么只要游客类实现观察者接口,那么一样可以将游客列入到作者的观察者列表中。
另外,我们让读者自己来选择自己关注的对象,这相当于被观察者将维护通知对象的职能转化给了观察者,这样做的好处是由于一个被观察者可能有N多观察者,所以让被观察者自己维护这个列表会很艰难,这就像一个老师被许多学生认识,那么是所有的学生都记住老师的名字简单,还是让老师记住N多学生的名字简单?答案显而易见,让学生们都记住一个老师的名字是最简单的。
另外,观察者模式分离了观察者和被观察者二者的责任,这样让类之间各自维护自己的功能,专注于自己的功能,会提高系统的可维护性和可重用性。
观察者模式其实还有另外一种形态,就是事件驱动模型,LZ个人觉得这两种方式大体上其实是非常相似的,所以LZ决定一起引入事件驱动模型。不过观察者更多的强调的是发布-订阅式的问题处理,而事件驱动则更多的注重于界面与数据模型之间的问题,两者还是有很多适用场景上的区别的,虽不能一概而论,但放在一起讨论还是很方便各位理解二者。
说到事件驱动,由于JAVA在桌面应用程序方面有很多欠缺,所以swing的使用其实并不是特别广泛,因为你不可能要求大多数人的机子上都安装了JDK,除非你是给特殊用户人群开发的应用程序,这些用户在你的可控范围内,那么swing或许可以派上用场。
考虑到学习JAVA或者使用JAVA的人群大部分都是在进行web开发,所以本次讨论事件驱动,采用web开发当中所用到的示例。
相信各位都知道tomcat,这是一个app服务器,在使用的过程中,或许经常会有人用到listener,即监听器这个概念。那么其实这个就是一个事件驱动模型的应用。比如我们的spring,我们在应用启动的时候要初始化我们的IOC容器,那么我们的做法就是加入一个listener,这样伴随着tomcat服务器的启动,spring的IOC容器就会跟着启动。
那么这个listener其实就是事件驱动模型中的监听器,它用来监听它所感兴趣的事,比如我们springIOC容器启动的监听器,就是实现的ServletContextListener这个接口,说明它对servletContext感兴趣,会监听servletContext的启动和销毁。
LZ不打算使用这个例子作为讲解,因为它的内部运作比较复杂,需要搬上来tomcat的源码,对于新手来说,这是个噩耗,所以我们将上述的例子改为事件驱动来实现。也好让各位针对性的对比观察者模式和事件驱动模型。
首先事件驱动模型与观察者模式勉强的对应关系可以看成是,被观察者相当于事件源,观察者相当于监听器,事件源会产生事件,监听器监听事件