私は基本的な設計上の問題を指摘することを単純化しています。関連クラスの複数訪問者
は、私はこのような階層構造を持っている:BRA
、BRB
、BRC
、RRA
、RRB
とRRC
が訪問する必要があるクラスがある
R <-- interface
/ \
/ \
/ \
BR RR <-- abstract classes
/| \ /| \
/| \ /| \
BRA BRB BRC RRA RRB RRC <-- classes
。
私はまた、共通の祖先クラスを共有していない2つのビジタークラスを持っています(今のところ)。だから、最終的には、コードは次のように構成されています
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>
、および各訪問者クラスのオブジェクトへの1つの参照を持っている、とする必要があります最も適切な訪問者を使用してキューのすべての要素を処理します。これは次のようになります:
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
を避けようとしている。
私の回避策は、このような何か、それらを区別するために抽象クラスBR
とRR
でpublic static final
列挙型フィールドを定義し、if
ブロックを使用することです:
@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)
}
}
をしかし結合するために、よりエレガントな解決策が存在しなければなりませんこれより2つのビジタークラス。
私はあなたがダブルディスパッチを探していると思います。 https://sourcemaking.com/design_patterns/visitor/java/2を参照してください。 –
@AdiLevin私はこの情報源を認識していますが、私の場合には調整できませんでした。 – chrk