谁说visitor不可以添加新元素?

这个visitor就可以随便添加,利用反射就可以做到了.
[code]
public abstract class Visitor {

final public void visit(Object object) {
Method method = getVisitMethod(object);
try {
method.invoke(this, new Object[] { object });
} catch (Exception e) {
String message = "invokeing method failed:visit("
+ object.getClass().getName() + ")";
throw new RuntimeException(message, e);
}
}

private Map visitMethods = new HashMap();

private Method getVisitMethod(Object object) {
//return (Method) visitMethods.get(object.getClass());
Iterator it = visitMethods.keySet().iterator();
for (; it.hasNext();) {
Class clazz = (Class) it.next();
if (clazz.isAssignableFrom(object.getClass())) {
return (Method) visitMethods.get(clazz);
}
}
throw new RuntimeException("method: visit(" + object.getClass().getName()
+ ") undefined in the class");
}

private Method visitMethod;

private void initVisitMethod() {
Method[] methods = getClass().getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
if (methods[i].getName().equals("visit")) {
Class[] paramTypes = methods[i].getParameterTypes();
if (paramTypes.length == 1) {
visitMethods.put(paramTypes[0], methods[i]);
}
}
}
}

{
initVisitMethod();
}
}
[/code]
下面是两个具体的Visitor
[code]
public class PrintVisitor extends Visitor{

public void visit(Float f){
System.out.println("float:"+f);
}
public void visit(Date date){
System.out.println("date:"+date);
}
public void visit(String str){
System.out.println("string:"+str);
}
}
[/code]
[code]
public class PrintVisitor2 extends Visitor{

public void visit(String str){
System.out.println("string2:"+str);
}
public void visit(List list){
System.out.println("list2:"+list);
}
}
[/code]
[code]
public void testVisit(){
ArrayList list = new ArrayList();
list.add("a");
list.add("b");
Visitor v = new PrintVisitor();
v.visit("hello");
v.visit(new Date());
Visitor v1 = new PrintVisitor2();
v1.visit("hello");
v1.visit(list);
}
[/code]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
一种解决方案是使用访问者模式的变体,称为双重分派访问者模式(Double Dispatch Visitor Pattern)。该模式通过在元素类中添加一个接受访问者的方法,以及在访问者类中添加多个访问元素的方法,实现了在运行时动态选择正确的访问方法的能力。 具体地,元素类中的方法将其自身传递给访问者,访问者根据元素的类型调用相应的方法,并将自身传递给该方法。这样,每个访问者只需要实现与其相关的元素的访问方法,而无需实现所有元素的访问方法,从而降低了耦合度。 例如,假设我们有一个员工类别的继承层次结构,包括普通员工、经理和CEO。我们可以将访问者类设计为一个接口,例如: ```java interface EmployeeVisitor { void visit(RegularEmployee employee); void visit(Manager manager); void visit(CEO ceo); } ``` 然后,在每个员工类别中添加一个接受访问者的方法: ```java class RegularEmployee { // ... void accept(EmployeeVisitor visitor) { visitor.visit(this); } } class Manager { // ... void accept(EmployeeVisitor visitor) { visitor.visit(this); } } class CEO { // ... void accept(EmployeeVisitor visitor) { visitor.visit(this); } } ``` 最后,我们可以实现具体的访问者类,例如计算员工薪水的访问者: ```java class SalaryCalculator implements EmployeeVisitor { double totalSalary = 0; void visit(RegularEmployee employee) { totalSalary += employee.getSalary(); } void visit(Manager manager) { totalSalary += manager.getSalary() + manager.getBonus(); } void visit(CEO ceo) { totalSalary += ceo.getSalary() + ceo.getBonus() + ceo.getStockOptions(); } double getTotalSalary() { return totalSalary; } } ``` 这样,当我们需要计算员工薪水时,可以创建一个SalaryCalculator对象,并依次访问每个员工对象: ```java RegularEmployee employee = new RegularEmployee("Alice", 5000); Manager manager = new Manager("Bob", 10000, 5000); CEO ceo = new CEO("Charlie", 20000, 10000, 5000); SalaryCalculator calculator = new SalaryCalculator(); employee.accept(calculator); manager.accept(calculator); ceo.accept(calculator); double totalSalary = calculator.getTotalSalary(); // totalSalary = 45000 ``` 这里的关键点是,每个员工对象只需要实现一个简单的accept方法,而无需知道具体的访问者类实现,从而降低了耦合度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值