使用访问者模式或反射的Java动态类转换?缺少步骤或执行不好?

时间:2013-09-02 06:53:12

标签: java class reflection casting

我正在根据用户输入创建具有共同属性的对象,然后将对象传递给将根据对象类型采取适当操作的公共方法。 我已经能够使用访问者类来完成这项工作,但这并不是我想要的。我希望能够在公共方法中确定对象类型,然后访问与该对象关联的方法。我不确定我是否接近并且只是缺少一些东西,或者我只是执行不好......或者两者都是=)。 这是我的(完整)代码:

package com.theory.bang.big;

public interface Particle
{
    public enum ParticleType {
        QUARK,
        LEPTON
}

int processParticle(Particle p);

}


package com.theory.bang.big;

import java.util.ArrayList;
public class Quark implements Particle
{
ArrayList<String> flavorList;

/**
 * Constructor for objects of class Quark
 */
public Quark() 
{
    flavorList = new ArrayList<String>();
    flavorList.add("up");
    flavorList.add("down");
    flavorList.add("charm");
    flavorList.add("strange");
    flavorList.add("top");
    flavorList.add("bottom");
}

public ArrayList<String> getFlavors()
{
    return flavorList;
}


@Override
public int processParticle(Particle p)
{
    System.out.println("In processParticle(Quark)");

    // Never called?

    return 0;
}

}



package com.theory.bang.big;

import java.util.ArrayList;

public class Lepton implements Particle
{
ArrayList<String> typeList;

/**
 * Constructor for objects of class Lepton
 */
public Lepton() 
{   
    typeList = new ArrayList<String>();
    typeList.add("electron");
    typeList.add("electron neutrino");
    typeList.add("muon");
    typeList.add("muon neutrino");
    typeList.add("tau");
    typeList.add("tau neutrino");
}

public ArrayList<String> getTypes()
{
    return typeList;
}

@Override
public int processParticle(Particle p)
{
    System.out.println("In processParticle(Lepton)");

    return 0;
}
}


package com.theory.bang.big;

import java.lang.reflect.*;

class ParticleVisitor
{
public void visit( Quark q )
{
    System.out.println("Quark:[" + q.getFlavors() + "]");
}

public void visit( Lepton l )
{
    System.out.println("Lepton:[" + l.getTypes() + "]");
}

public void visit( Object e ) throws Exception
{
    Method m = getClass().getMethod
     ( "visit", new Class[]{e.getClass()} );
    m.invoke( this, new Object[]{e} );
}
}


package com.theory.bang.big;

import java.io.File;

public class Accelerate implements Particle
{
/**
 * Constructor for objects of class Accelerate
 */
public Accelerate(Particle p)
{
    processParticle(p);
}

//@Override
public int processParticle(Particle p)
{
    try {

        ParticleVisitor pv = new ParticleVisitor();
        pv.visit(p);
    } catch (Exception x) {
        System.out.println(x);
    }

   return 0;
}
}


package com.theory.bang.big;

import java.io.File;
import java.util.Scanner;

public class Physics
{
public static void main(String[] args)
{
   boolean done = false;

   while (!done) {
       System.out.print("Enter the particle [Quark or Lepton]: ");
       Scanner in = new Scanner(System.in);      
       String input = in.next();

       if (input.equals("Quark")) {
           System.out.println("Quark");
           Quark q = new Quark();
           new Accelerate(q);
        } else if (input.equals("Lepton")) {
            System.out.println("Lepton");
            Lepton l = new Lepton();
            new Accelerate(l);
        } else {
            done = true;
        }
    }

}
}

目前我可以通过访问方法打印Quark风格和Lepton类型,但我需要的是能够执行(实现)getter / setter(例如getSpin(),setSpin(double s)) Accelerate()中的对象。 我错过了什么?或者有更好的方法来实现这个吗?

非常感谢你的时间。

-Walter

1 个答案:

答案 0 :(得分:0)

对于您的具体示例,您可以丢弃所有内容并使用参数类型进行重载:

public class Physics {
    public static void processParticle( Quark q ) {
        System.out.println("Quark:[" + q.getFlavors() + "]");
    }

    public static void processParticle( Lepton l ) {
        System.out.println("Lepton:[" + l.getTypes() + "]");
    }

    public static void main(String[] args) {
    boolean done = false;

    while (!done) {
       System.out.print("Enter the particle [Quark or Lepton]: ");
       Scanner in = new Scanner(System.in);      
       String input = in.next();

       if (input.equals("Quark")) {
           System.out.println("Quark");
           Quark q = new Quark();
           processParticle(q);
        } else if (input.equals("Lepton")) {
           System.out.println("Lepton");
           Lepton l = new Lepton();
           processParticle(q);
       } else {
           done = true;
    }
}

如果要调用processParticle(),其中编译器不知道粒子的确切类型,请使用double dispatch pattern:

// add method processParticle
public interface Particle{
    ...

    void processParticle();

}

 class Quark implements Particle {
    void processParticle() {
        Physics.processParticle(this);
    }
 }

 class Lepton extends Particle {
    void processParticle() {
        Physics.processParticle(this);
    }
 }

 public class Physics {

    public static void main(String[] args) {
        for (;;) {
           System.out.print("Enter the particle [Quark or Lepton]: ");
           Scanner in = new Scanner(System.in);      
           String input = in.next();
           Particle p;
           if (input.equals("Quark")) {
               System.out.println("Quark");
               p = new Quark();
            } else if (input.equals("Lepton")) {
               System.out.println("Lepton");
               p = new Lepton();
           } else {
              break;
           }
           p.processParticle();
        }
    }
}

然后你可以演变为真正的访客模式,但这里可以而且应该避免反思。