1700478614
设计模式之禅 32.3 观察者模式VS责任链模式
1700478615
1700478616
为什么要把观察者模式和责任链模式放在一起对比呢?看起来这两个模式没有太多的相似性,真没有吗?回答是有。我们在观察者模式中也提到了触发链(也叫做观察者链)的问题,一个具体的角色既可以是观察者,也可以是被观察者,这样就形成了一个观察者链。这与责任链模式非常类似,它们都实现了事务的链条化处理,比如说在上课的时候你睡着了,打鼾声音太大,盖过了老师讲课声音,老师火了,捅到了校长这里,校长也处理不了,然后告状给你父母,于是你的魔鬼日子来临了,这是责任链模式,老师、校长、父母都是链中的一个具体角色,事件(你睡觉)在链中传递,最终由一个具体的节点来处理,并将结果反馈给调用者(你挨揍了)。那什么是触发链?你还是在课堂上睡觉,还是打鼾声音太大,老师火了,但是老师掏出个扩音器来讲课,于是你睡不着了,同时其他同学的耳朵遭殃了,这就是触发链,其中老师既是观察者(相对你)也是被观察者(相对其他同学),事件从“你睡觉”到老师这里转化为“扩音器放大声音”,这也是一个链条结构,但是链结构中传递的事件改变了。
1700478617
1700478618
我们还是以一个具体的例子来说明两者的区别,DNS协议相信大家都听说过,只要在“网络设置”中设置一个DNS服务器地址就可以把我们需要的域名翻译成IP地址。DNS协议还是比较简单的,传递过去一个域名以及记录标志(比如是要A记录还是要MX记录),DNS就开始查找自己的记录树,找到后把IP地址反馈给请求者。我们可以在Windows操作系统中了解一下DNS解析过程,在DOS窗口下输入nslookup命令后,结果如图32-6所示。
1700478619
1700478620
1700478621
1700478622
1700478623
图32-6 DNS服务器解析域名
1700478624
1700478625
我们的意图就是要DNS服务器192.168.10.1解析出www.xxx.com.cn的IP地址,DNS服务器是如何工作的呢?图32-6中的192.168.10.1这个DNS Server存储着全球的域名和IP之间的对应关系吗?不可能,目前全球的域名数量是1.7亿个,如此庞大的数字,每个DNS服务器都存储一份,还怎么快速响应?DNS解析的响应时间一般都是毫秒级别的,如此高的性能要求还怎么让DNS服务器遍地开花呢?而且域名变更非常频繁,数据读写的量也非常大,不可能每个DNS服务器都保留这1.7亿数据,那么是怎么设计的呢?DNS协议还是很聪明的,它规定了每个区域的DNS服务器(Local DNS)只保留自己区域的域名解析,对于不能解析的域名,则提交上级域名解析器解析,最终由一台位于美国洛杉矶的顶级域名服务器进行解析,返回结果。很明显这是一个事务的链结构处理,我们使用两种模式来实现该解析过程。
1700478626
1700478627
32.3.1 责任链模式实现DNS解析过程
1700478628
1700478629
本小节我们用责任链模式来实现DNS解析过程。首先我们定义一下业务场景,这里有三个DNS服务器:上海DNS服务器(区域服务器)、中国顶级DNS服务器(父服务器)、全球顶级DNS服务器,其示意图如图32-7所示。
1700478630
1700478631
1700478632
1700478633
1700478634
图32-7 DNS解析示意图
1700478635
1700478636
假设有请求者发出请求,由上海DNS进行解析,如果能够解析,则返回结果,若不能解析,则提交给父服务器(中国顶级DNS)进行解析,若还不能解析,则提交到全球顶级DNS进行解析,若还不能解析呢?那就返回该域名无法解析。确实,这与责任链模式非常相似,我们把这一过程抽象一下,类图如图32-8所示。
1700478637
1700478638
1700478639
1700478640
1700478641
图32-8 责任链模式实现DNS解析的类图
1700478642
1700478643
我们来解释一下类图,Recorder是一个BO对象,它记录DNS服务器解析后的结果,包括域名、IP地址、属主(即由谁解析的),除此之外还有getter/setter方法。DnsServer抽象类中的resolve方法是一个基本方法,每个DNS服务器都必须拥有该方法,它对DNS进行解析,如何解析呢?具体是由echo方法来实现的,每个DNS服务器独自实现。类图还是比较简单的,我们首先看一下解析记录Recorder类,如代码清单32-31所示。
1700478644
1700478645
代码清单32-31 解析记录
1700478646
1700478647
public class Recorder{
1700478648
1700478649
//域名
1700478650
1700478651
private String domain;
1700478652
1700478653
//IP地址
1700478654
1700478655
private String ip;
1700478656
1700478657
//属主
1700478658
1700478659
private String owner;
1700478660
1700478661
public String getDomain(){
1700478662
[
上一页 ]
[ :1.700478613e+09 ]
[
下一页 ]