<b>访谒器范式</b>[Java编程]
本文“<b>访谒器范式</b>[Java编程]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:
接下来,让我们考虑若何将具有完好差别目标的一个计划范式利用到垃圾归类系统.
对这个范式,我们不再关心在系统中加入新型Trash时的优化.事实上,这个范式使新型Trash的增添显得越发复杂.假定我们有一个基本类构造,它是固定不变的;它大概来自另一个开辟者或公司,我们无权对那个构造举行任何改正.但是,我们又但愿在那个构造里加入新的多形性办法.这意味着我们普通必须在底子类的接口里增添某些东西.因此,我们目前面对的窘境是一方面需求向底子类增添办法,另一方面又不能窜改底子类.怎样办理这个问题呢?
“拜候器”(Visitor)范式使我们能扩大基本范例的接口,办法是成立范例为Visitor的一个独立的类构造,对今后需对基本范例采纳的操作举行虚拟.基本范例的任务就是简单地“接纳”拜候器,然后调用拜候器的动态绑定办法.看起来就象下面这样:
目前,假定v是一个指向Aluminum(铝制品)的Visitable句柄,那么下述代码:
PriceVisitor pv = new PriceVisitor();
v.accept(pv);
会造成两个多形性办法调用:第一个会挑选accept()的Aluminum版本;第二个则在accept()里——用底子类Visitor句柄v动态调用visit()的特定版本时.
这种配置意味着可采纳Visitor的新子类的情势将新的功效增添到系统里,没必要接触Trash构造.这就是“拜候器”范式最主要的长处:可为一个类构造增添新的多形性功效,同时没必要窜改构造——只要安装好了accept()办法.注意这个长处在这儿是有效的,但并不一定是我们在任何情形下的首选筹划.所以在最开始的时刻,就要判断这毕竟是不是自己需求的筹划.
目前注意一件没有做成的事情:拜候器筹划避免了从主控Trash序列向单独范例序列的归类.所以我们可将全部东西都留在单主控序列中,只需用得当的拜候器通过那个序列传送,便可到达但愿的目标.固然这仿佛并非拜候器范式的本意,但确切让我们到达了很但愿到达的一个目标(避免利用RTTI).
拜候器范式中的双生调派负责同时判断Trash以及Visitor的范例.在下面的例子中,大家可看到Visitor的两种实现方法:PriceVisitor用于判断总计及价钱,而WeightVisitor用于跟踪重量.
可以看到,全部这些都是用回收程序一个新的、改良过的版本实现的.并且和DoubleDispatch.java一样,Trash类被保持孤独,并成立一个新接口来增添accept()办法:
//: Visitable.java // An interface to add visitor functionality to // the Trash hierarchy without modifying the // base class. package c16.trashvisitor; import c16.trash.*; interface Visitable { // The new method: void accept(Visitor v); } ///:~
Aluminum,Paper,Glass以及Cardboard的子范例实现了accept()办法:
//: VAluminum.java // Aluminum for the visitor pattern package c16.trashvisitor; import c16.trash.*; public class VAluminum extends Aluminum implements Visitable { public VAluminum(double wt) { super(wt); } public void accept(Visitor v) { v.visit(this); } } ///:~
//: VPaper.java // Paper for the visitor pattern package c16.trashvisitor; import c16.trash.*; public class VPaper extends Paper implements Visitable { public VPaper(double wt) { super(wt); } public void accept(Visitor v) { v.visit(this); } } ///:~
//: VGlass.java // Glass for the visitor pattern package c16.trashvisitor; import c16.trash.*; public class VGlass extends Glass implements Visitable { public VGlass(double wt) { super(wt); } public void accept(Visitor v) { v.visit(this); } } ///:~
//: VCardboard.java // Cardboard for the visitor pattern package c16.trashvisitor; import c16.trash.*; public class VCardboard extends Cardboard implements Visitable { public VCardboard(double wt) { super(wt); } public void accept(Visitor v) { v.visit(this); } } ///:~
由于Visitor底子类没有什么需求实在的东西,可将其成立成一个接口:
//: Visitor.java // The base interface for visitors package c16.trashvisitor; import c16.trash.*; interface Visitor { void visit(VAluminum a); void visit(VPaper p); void visit(VGlass g); void visit(VCardboard c); } ///:~
c16.TrashVisitor.VGlass:54 c16.TrashVisitor.VPaper:22 c16.TrashVisitor.VPaper:11 c16.TrashVisitor.VGlass:17 c16.TrashVisitor.VAluminum:89 c16.TrashVisitor.VPaper:88 c16.TrashVisitor.VAluminum:76 c16.TrashVisitor.VCardboard:96 c16.TrashVisitor.VAluminum:25 c16.TrashVisitor.VAluminum:34 c16.TrashVisitor.VGlass:11 c16.TrashVisitor.VGlass:68 c16.TrashVisitor.VGlass:43 c16.TrashVisitor.VAluminum:27 c16.TrashVisitor.VCardboard:44 c16.TrashVisitor.VAluminum:18 c16.TrashVisitor.VPaper:91 c16.TrashVisitor.VGlass:63 c16.TrashVisitor.VGlass:50 c16.TrashVisitor.VGlass:80 c16.TrashVisitor.VAluminum:81 c16.TrashVisitor.VCardboard:12 c16.TrashVisitor.VGlass:12 c16.TrashVisitor.VGlass:54 c16.TrashVisitor.VAluminum:36 c16.TrashVisitor.VAluminum:93 c16.TrashVisitor.VGlass:93 c16.TrashVisitor.VPaper:80 c16.TrashVisitor.VGlass:36 c16.TrashVisitor.VGlass:12 c16.TrashVisitor.VGlass:60 c16.TrashVisitor.VPaper:66 c16.TrashVisitor.VAluminum:36 c16.TrashVisitor.VCardboard:22
程序剩余的部份将成立特定的Visitor范例,并通过一个Trash对象列表发送它们:
//: TrashVisitor.java // The "visitor" pattern package c16.trashvisitor; import c16.trash.*; import java.util.*; // Specific group of algorithms packaged // in each implementation of Visitor: class PriceVisitor implements Visitor { private double alSum; // Aluminum private double pSum; // Paper private double gSum; // Glass private double cSum; // Cardboard public void visit(VAluminum al) { double v = al.weight() * al.value(); System.out.println( "value of Aluminum= " + v); alSum += v; } public void visit(VPaper p) { double v = p.weight() * p.value(); System.out.println( "value of Paper= " + v); pSum += v; } public void visit(VGlass g) { double v = g.weight() * g.value(); System.out.println( "value of Glass= " + v); gSum += v; } public void visit(VCardboard c) { double v = c.weight() * c.value(); System.out.println( "value of Cardboard = " + v); cSum += v; } void total() { System.out.println( "Total Aluminum: ___FCKpd___7quot; + alSum + "\n" + "Total Paper: ___FCKpd___7quot; + pSum + "\n" + "Total Glass: ___FCKpd___7quot; + gSum + "\n" + "Total Cardboard: ___FCKpd___7quot; + cSum); } } class WeightVisitor implements Visitor { private double alSum; // Aluminum private double pSum; // Paper private double gSum; // Glass private double cSum; // Cardboard public void visit(VAluminum al) { alSum += al.weight(); System.out.println("weight of Aluminum = " + al.weight()); } public void visit(VPaper p) { pSum += p.weight(); System.out.println("weight of Paper = " + p.weight()); } public void visit(VGlass g) { gSum += g.weight(); System.out.println("weight of Glass = " + g.weight()); } public void visit(VCardboard c) { cSum += c.weight(); System.out.println("weight of Cardboard = " + c.weight()); } void total() { System.out.println("Total weight Aluminum:" + alSum); System.out.println("Total weight Paper:" + pSum); System.out.println("Total weight Glass:" + gSum); System.out.println("Total weight Cardboard:" + cSum); } } public class TrashVisitor { public static void main(String[] args) { Vector bin = new Vector(); // ParseTrash still works, without changes: ParseTrash.fillBin("VTrash.dat", bin); // You could even iterate through // a list of visitors! PriceVisitor pv = new PriceVisitor(); WeightVisitor wv = new WeightVisitor(); Enumeration it = bin.elements(); while(it.hasMoreElements()) { Visitable v = (Visitable)it.nextElement(); v.accept(pv); v.accept(wv); } pv.total(); wv.total(); } } ///:~
注意main()的形状已再次发生了改变.目前只有一个垃圾(Trash)筒.两个Visitor对象被接纳到序列中的每个元素内,它们会完成自己份内的工作.Visitor跟踪它们自己的内部数据,计算出总重和价钱.
最好,将东西从序列中取出的时刻,除了不可避免地向Trash造型以外,再没有运行期的范例考证.若在Java里实现了参数化范例,乃至那个造型操作也可以避免.
比较之前介绍过的双重调派筹划,辨别这两种筹划的一个办法是:在双重调派筹划中,每个子类成立时只会过载此中的一个过载办法,即add().而在这里,每个过载的visit()办法都必须在Visitor的每个子类中举行过载.
1. 更多的结合?
这里还有其他很多代码,Trash构造和Visitor构造之间存在着明显的“结合”(Coupling)关系.但是,在它们所代表的类集内部,也存在着高度的凝集力:都只做一件事情(Trash描写垃圾或废品,而Visitor描写对垃圾采纳什么行动).作为一套优异的计划筹划,这无疑是个杰出的初阶.当然就目前的情形来说,只有在我们增添新的Visitor范例时才能领会到它的好处.但在增添新范例的Trash时,它却显得有些碍手碍脚.
类与类之间低度的结合与类内高度的凝集无疑是一个重要的计划目标.但只要略不留神,便大概阻碍我们得到一个本该更超卓的计划.从表面看,有些类不可避免地彼此间存在着一些“密切”关系.这种关系普通是成对发生的,可以叫作“春联”(Couplet)——比方调集和担当器(Enumeration).前面的Trash-Visitor对仿佛也是这样的一种“春联”.
以上是“<b>访谒器范式</b>[Java编程]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
本文地址: | 与您的QQ/BBS好友分享! |
- ·上一篇文章:<b>RTTI有害吗</b>
- ·下一篇文章:实现双重调派
- ·中查找“<b>访谒器范式</b>”更多相关内容
- ·中查找“<b>访谒器范式</b>”更多相关内容