Java 相关课程的多个访问者

Java 相关课程的多个访问者,java,design-patterns,architecture,visitor,visitor-pattern,Java,Design Patterns,Architecture,Visitor,Visitor Pattern,我正在简化一些东西,以指出我的基本设计问题 我有这样的层次结构: R <-- interface / \ / \ / \ BR RR <-- abstract classes / | \ / | \ / | \ / | \ BRA BR

我正在简化一些东西,以指出我的基本设计问题

我有这样的层次结构:

              R                <-- interface
            /   \
           /     \
          /       \
        BR         RR          <-- abstract classes
      / | \       / | \
     /  |  \     /  |  \
  BRA BRB BRC  RRA RRB RRC     <-- classes
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 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. ***/

        }
    }
}
@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)
    }
}
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);
    }
}


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

              R                <-- interface
            /   \
           /     \
          /       \
        BR         RR          <-- abstract classes
      / | \       / | \
     /  |  \     /  |  \
  BRA BRB BRC  RRA RRB RRC     <-- classes
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 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. ***/

        }
    }
}
@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)
    }
}
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);
    }
}

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

这里是一个访问者模式的示例。请注意,这里有一个界面访问者,它为每种类型的访问点提供了
visit()
方法

public class Demo {
    public static void main ( String [] args ) {
        Point p = new Point2d( 1, 2 );
        Visitor v = new Chebyshev();
        p.accept( v );
        System.out.println( p.getMetric() );
    }
}

interface Visitor {
    public void visit ( Point2d p );
    public void visit ( Point3d p );
}

abstract class Point {
    public abstract void accept ( Visitor v );
    private double metric = -1;
    public double getMetric () {
        return metric;
    }
    public void setMetric ( double metric ) {
        this.metric = metric;
    }
}

class Point2d extends Point {
    public Point2d ( double x, double y ) {
        this.x = x;
        this.y = y;
    }

    public void accept ( Visitor v ) {
        v.visit( this );
    }

    private double x;
    public double getX () { return x; }

    private double y;
    public double getY () { return y; }
}

class Point3d extends Point {
    public Point3d ( double x, double y, double z ) {
        this.x = x;
        this.y = y;
        this.z = z;
    }
    public void accept ( Visitor v ) {
        v.visit( this );
    }

    private double x;
    public double getX () { return x; }

    private double y;
    public double getY () { return y; }

    private double z;
    public double getZ () { return z; }
}

class Euclid implements Visitor {
    public void visit ( Point2d p ) {
        p.setMetric( Math.sqrt( p.getX()*p.getX() + p.getY()*p.getY() ) );
    }
    public void visit ( Point3d p ) {
        p.setMetric( Math.sqrt( p.getX()*p.getX() + p.getY()*p.getY() + p.getZ()*p.getZ() ) );
    }
}

class Chebyshev implements Visitor {
    public void visit ( Point2d p ) {
        double ax = Math.abs( p.getX() );
        double ay = Math.abs( p.getY() );
        p.setMetric( ax>ay ? ax : ay );
    }
    public void visit ( Point3d p ) {
        double ax = Math.abs( p.getX() );
        double ay = Math.abs( p.getY() );
        double az = Math.abs( p.getZ() );
        double max = ax>ay ? ax : ay;
        if ( max<az ) max = az;
        p.setMetric( max );
    }
}
公共类演示{
公共静态void main(字符串[]args){
点p=新点2D(1,2);
访客v=新切比雪夫();
p、 接受(v);
System.out.println(p.getMetric());
}
}
界面访问者{
公众访问(点2D p);
公众访问(Point3d p);
}
抽象类点{
公开摘要无效接受(访客v);
私有双指标=-1;
公共双getMetric(){
返回度量;
}
公共无效集合度量(双度量){
this.metric=metric;
}
}
类Point2d扩展了Point{
公共点2D(双x,双y){
这个.x=x;
这个。y=y;
}
公众无效接受(访客v){
v、 访问(本);
}
私人双x;
公共双getX(){return x;}
私人双y;
公共双getY(){return y;}
}
类Point3d扩展了Point{
公共点3D(双x、双y、双z){
这个.x=x;
这个。y=y;
这个。z=z;
}
公众无效接受(访客v){
v、 访问(本);
}
私人双x;
公共双getX(){return x;}
私人双y;
公共双getY(){return y;}
私人双z;
公共双getZ(){return z;}
}
类Euclid实现访问者{
公众访问(点2D p){
p、 setMetric(Math.sqrt(p.getX()*p.getX()+p.getY()*p.getY());
}
公众无效访问(Point3d p){
p、 setMetric(Math.sqrt(p.getX()*p.getX()+p.getY()*p.getY()+p.getZ()*p.getZ());
}
}
类Chebyshev实现了Visitor{
公众访问(点2D p){
double ax=Math.abs(p.getX());
double-ay=Math.abs(p.getY());
p、 setMetric(ax>ay?ax:ay);
}
公众无效访问(Point3d p){
double ax=Math.abs(p.getX());
double-ay=Math.abs(p.getY());
double az=Math.abs(p.getZ());
双倍最大值=ax>ay?ax:ay;

if(max这里是一个访问者模式的示例。请注意,这里是一个界面访问者,它对每种类型的访问点使用
visit()
方法

public class Demo {
    public static void main ( String [] args ) {
        Point p = new Point2d( 1, 2 );
        Visitor v = new Chebyshev();
        p.accept( v );
        System.out.println( p.getMetric() );
    }
}

interface Visitor {
    public void visit ( Point2d p );
    public void visit ( Point3d p );
}

abstract class Point {
    public abstract void accept ( Visitor v );
    private double metric = -1;
    public double getMetric () {
        return metric;
    }
    public void setMetric ( double metric ) {
        this.metric = metric;
    }
}

class Point2d extends Point {
    public Point2d ( double x, double y ) {
        this.x = x;
        this.y = y;
    }

    public void accept ( Visitor v ) {
        v.visit( this );
    }

    private double x;
    public double getX () { return x; }

    private double y;
    public double getY () { return y; }
}

class Point3d extends Point {
    public Point3d ( double x, double y, double z ) {
        this.x = x;
        this.y = y;
        this.z = z;
    }
    public void accept ( Visitor v ) {
        v.visit( this );
    }

    private double x;
    public double getX () { return x; }

    private double y;
    public double getY () { return y; }

    private double z;
    public double getZ () { return z; }
}

class Euclid implements Visitor {
    public void visit ( Point2d p ) {
        p.setMetric( Math.sqrt( p.getX()*p.getX() + p.getY()*p.getY() ) );
    }
    public void visit ( Point3d p ) {
        p.setMetric( Math.sqrt( p.getX()*p.getX() + p.getY()*p.getY() + p.getZ()*p.getZ() ) );
    }
}

class Chebyshev implements Visitor {
    public void visit ( Point2d p ) {
        double ax = Math.abs( p.getX() );
        double ay = Math.abs( p.getY() );
        p.setMetric( ax>ay ? ax : ay );
    }
    public void visit ( Point3d p ) {
        double ax = Math.abs( p.getX() );
        double ay = Math.abs( p.getY() );
        double az = Math.abs( p.getZ() );
        double max = ax>ay ? ax : ay;
        if ( max<az ) max = az;
        p.setMetric( max );
    }
}
公共类演示{
公共静态void main(字符串[]args){
点p=新点2D(1,2);
访客v=新切比雪夫();
p、 接受(v);
System.out.println(p.getMetric());
}
}
界面访问者{
公众访问(点2D p);
公众访问(Point3d p);
}
抽象类点{
公开摘要无效接受(访客v);
私有双指标=-1;
公共双getMetric(){
返回度量;
}
公共无效集合度量(双度量){
this.metric=metric;
}
}
类Point2d扩展了Point{
公共点2D(双x,双y){
这个.x=x;
这个。y=y;
}
公众无效接受(访客v){
v、 访问(本);
}
私人双x;
公共双getX(){return x;}
私人双y;
公共双getY(){return y;}
}
类Point3d扩展了Point{
公共点3D(双x、双y、双z){
这个.x=x;
这个。y=y;
这个。z=z;
}
公众无效接受(访客v){
v、 访问(本);
}
私人双x;
公共双getX(){return x;}
私人双y;
公共双getY(){return y;}
私人双z;
公共双getZ(){return z;}
}
类Euclid实现访问者{
公众访问(点2D p){
p、 setMetric(Math.sqrt(p.getX()*p.getX()+p.getY()*p.getY());
}
公众无效访问(Point3d p){
p、 setMetric(Math.sqrt(p.getX()*p.getX()+p.getY()*p.getY()+p.getZ()*p.getZ());
}
}
类Chebyshev实现了Visitor{
公众访问(点2D p){
double ax=Math.abs(p.getX());
double-ay=Math.abs(p.getY());
p、 setMetric(ax>ay?ax:ay);
}
公众无效访问(Point3d p){
double ax=Math.abs(p.getX());
double-ay=Math.abs(p.getY());
double az=Math.abs(p.getZ());
双倍最大值=ax>ay?ax:ay;

如果(max好的话,我想我现在已经想出了更好的办法,灵感来自于。然而,我仍然对优雅的解决方案持开放态度

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

public interface R {
    /* . . . */
    public accept(SelectiveVisitor sv);
}
因此,
BR
RR
修改如下:

              R                <-- interface
            /   \
           /     \
          /       \
        BR         RR          <-- abstract classes
      / | \       / | \
     /  |  \     /  |  \
  BRA BRB BRC  RRA RRB RRC     <-- classes
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 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. ***/

        }
    }
}
@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)
    }
}
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);
    }
}
新类的定义如下:

              R                <-- interface
            /   \
           /     \
          /       \
        BR         RR          <-- abstract classes
      / | \       / | \
     /  |  \     /  |  \
  BRA BRB BRC  RRA RRB RRC     <-- classes
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 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. ***/

        }
    }
}
@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)
    }
}
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);
    }
}
客户端
现在更改为:

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

    /* . . . */

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

            r.accept(sv);
        }
    }
}
公共类客户端实现可运行{
私家侦探;
私有阻塞队列q;
/* . . . */
@凌驾
无效运行(){
对于(;;){
R=q.take();
r、 接受(sv);
}
}
}
每次调用
r.accept(selectiveVisitor)
时,
selectiveVisitor
类的
visit
方法由
BR
RR
的子类之一调用

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


我要离开这里了,