gpt4 book ai didi

java - 相关类(class)的多名访客

转载 作者:行者123 更新时间:2023-12-01 10:09:38 26 4
gpt4 key购买 nike

我正在简化事情以指出我的基本设计问题。

我有这样的层次结构:

              R                <-- interface
/ \
/ \
/ \
BR RR <-- abstract classes
/ | \ / | \
/ | \ / | \
BRA BRB BRC RRA RRB RRC <-- classes

哪里BRA , BRB , BRC , RRA , RRBRRC是需要参观的类(class)。

我还有两个访问者类,它们不共享任何共同的祖先类(目前)。所以,最后,代码的结构如下:

public interface R {
/* . . . */
}

public abstract class BR implements R {
/* . . . */
public abstract void accept(VisitorBR vbr);
}

public abstract class RR implements R {
/* . . . */
public abstract void accept(VisitorRR vrr);
}


public class BRA extends BR {
/* . . . */
public void accept(VisitorBR vbr) { vbr.visit(this); }
}

public class BRB extends BR {
/* . . . */
public void accept(VisitorBR vbr) { vbr.visit(this); }
}

public class BRC extends BR {
/* . . . */
public void accept(VisitorBR vbr) { vbr.visit(this); }
}


public class RRA extends RR {
/* . . . */
public void accept(VisitorRR vrr) { vrr.visit(this); }
}

public class RRB extends RR {
/* . . . */
public void accept(VisitorRR vrr) { vrr.visit(this); }
}

public class RRC extends RR {
/* . . . */
public void accept(VisitorRR vrr) { vrr.visit(this); }
}

public class VisitorBR {
/* . . . */
public void visit(BRA r) { /* . . . */ }
public void visit(BRB r) { /* . . . */ }
public void visit(BRC r) { /* . . . */ }
}

public class VisitorRR {
/* . . . */
public void visit(RRA r) { /* . . . */ }
public void visit(RRB r) { /* . . . */ }
public void visit(RRC r) { /* . . . */ }
}
<小时/>

客户端类有 BlockingQueue<R> ,以及对每个访问者类的对象的一个​​引用,并且需要使用最合适的访问者来处理队列的所有元素。看起来像这样:

public class Client implements Runnable {
private VisitorBR vbr;
private VisitorRR vrr;
private BlockingQueue<R> q;

/* . . . */

@Override
void run() {
for (;;) {
R r = q.take();

/*** Somehow handle r with the most suitable visitor, ***/
/*** based on whether it's descendant of BR or RR. ***/

}
}
}

最优雅的解决方案是什么?顺便说一句,无论如何,访问者不能是嵌套类,我试图避免使用 instanceof .

我的解决方法是定义 public static final抽象类中的枚举字段BRRR来区分它们,并使用 if block ,像这样:

@Override
void run() {
for (;;) {
R r = q.take();

if (r.getType() == BR)
((BR) r).accept(vbr);
else // if (r.getType() == RR)
((RR) r).accept(vrr)
}
}

但是必须有一个比这更优雅的解决方案来组合两个访问者类。

最佳答案

好吧,我想我现在已经想到了更好的办法,受到 Selective Visitor Pattern, as described here 的启发 。不过,我仍然对优雅的解决方案持开放态度。

定义了一个新类SelectiveVisitor,它现在是对Client 拥有的访问者类的唯一引用。接口(interface) R 现在声明了一个附加方法:

public interface R {
/* . . . */
public accept(SelectiveVisitor sv);
}

因此,BRRR 修改如下:

public abstract class BR implements R {        
/* . . . */
public void accept(SelectiveVisitor sv) {
sv.visit(this);
}
public abstract void accept(VisitorBR vbr);
}

public abstract class RR implements R {
/* . . . */
public void accept(SelectiveVisitor sv) {
sv.visit(this);
}
public abstract void accept(VisitorRR vrr);
}

新类的定义如下:

public class SelectiveVisitor {
private VisitorBR vbr;
private VisitorRR vrr;

public SelectiveVisitor(VisitorBR vbr, VisitorRR vrr) {
this.vbr = vbr;
this.vrr = vrr;
}

public void visit(R r) {
// this method should never be called in practice
// it's here only to satisfy the selective visitor pattern
return;
}

public void visit(BR r) {
r.accept(this.vbr);
}

public void visit(RR r) {
r.accept(this.vrr);
}
}

Client 现在更改为:

public class Client implements Runnable {
private SelectiveVisitor sv;
private BlockingQueue<R> q;

/* . . . */

@Override
void run() {
for (;;) {
R r = q.take();

r.accept(sv);
}
}
}

每次调用 r.accept(selectiveVisitor) 时,SelectiveVisitor 类的 visit 方法都会由BRRR

SelectiveVisitor 类的 visit 方法已重载。每次调用时,都会动态选择最具体的版本,从而最合适的访问者访问r

<小时/>

我将这篇文章留在这里,以防将来有人偶然发现类似的设计问题,而那时还没有提出更好的方案。

关于java - 相关类(class)的多名访客,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36214262/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com