16.7 访问器范式
16.7 访问器范式
接下来,让我们思考如何将具有完全不同目标的一个设计范式应用到垃圾归类系统。
对这个范式,我们不再关心在系统中加入新型
“访问器”(Visitor)范式使我们能扩展基本类型的接口,方法是创建类型为

现在,假如
PriceVisitor pv = new PriceVisitor();
v.accept(pv);
会造成两个多态性方法调用:第一个会选择
这种配置意味着可采取
现在注意一件没有做成的事情:访问器方案防止了从主控
访问器范式中的双生派遣负责同时判断
可以看到,所有这些都是用回收程序一个新的、改进过的版本实现的。而且和
//: 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,
//: 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.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
程序剩余的部分将创建特定的
//: 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: $" + alSum + "\n" +
"Total Paper: $" + pSum + "\n" +
"Total Glass: $" + gSum + "\n" +
"Total Cardboard: $" + 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();
}
} ///:~
注意
最好,将东西从序列中取出的时候,除了不可避免地向
对比之前介绍过的双重派遣方案,区分这两种方案的一个办法是:在双重派遣方案中,每个子类创建时只会重载其中的一个重载方法,即
- 更多的结合?
这里还有其他许多代码,
类与类之间低度的结合与类内高度的凝聚无疑是一个重要的设计目标。但只要稍不留神,就可能妨碍我们得到一个本该更出色的设计。从表面看,有些类不可避免地相互间存在着一些“亲密”关系。这种关系通常是成对发生的,可以叫作“对联”(Couplet)——比如集合和迭代器(Enumeration