句柄操作符的动态程序

时间:2015-08-24 04:43:56

标签: java

我有一个处理数学运算符的程序(+,*, - ,/)。我有一个接口运算符,它有一个像这样的计算方法:

public interface Operator
{
    double calculate(double firstNumber,double secondNumber);
}

我有四个类(Plus,Minus,Divide,Multiply)实现了Operator接口,如下所示:

public class Plus implements Operator
{   
    public double calculate(double firstNumber,double secondNumber)
    {
        return firstNumber + secondNumber;
    }
}

public class Minus implements Operator
{
    public double calculate(double firstNumber,double secondNumber)
    {
        return firstNumber - secondNumber;
    }
}

等等......

我使用Map来处理运算符:

static Map<String,Operator> operatorMap = new HashMap<String,Operator>();
static
{
    operatorMap.put("+", new Plus());
    operatorMap.put("-", new Minus());
    operatorMap.put("*", new Multiply());
    operatorMap.put("/", new Divide());
}

double output = operatorMap.get(op).calculate(firstNumber,secondNumber);

我应该像这样更改程序:

我有一个文件夹(myfolder)。每个人都可以获取界面并实现自己的操作符并将.class文件放在myfolder中。我的程序也应该工作。这意味着依赖于(+,*, - ,/)应该删除从我的程序。 例如,有些人获得操作员界面并实现%并将.class文件放在我的文件夹中,我的程序仍然可以工作(地图实现必须更改) 谁能帮我? 我很欣赏。

3 个答案:

答案 0 :(得分:1)

所以你的意思是你将为一个新的操作符创建一个新类,程序应该自动选择它。如果是这种情况,您可以使用Reflection API来迭代实现Operator接口的可用类。然后将它们添加到地图中。

要删除对hashmap的依赖项,可以在Operator界面中添加一个新方法,如下所示:

public interface Operator
{
  double calculate(double firstNumber,double secondNumber);
  char getSign();
}

像Plus,Minus这样的所有类都会返回一个映射到其符号的字符。

public class Plus implements Operator
{   
  public double calculate(double firstNumber,double secondNumber)
  {
     return firstNumber + secondNumber;
  }
  public char getSign()
  {
     return '+';
  }
}

接下来,在您的calculate(char operator, int operand1, int operand2)方法中,您可以首先遍历实现Operator接口的所有类(使用反射),然后调用get sign并将其与传递给此方法的operator参数进行比较,如果符号与运算符,将操作数传递给Operator.calculate()方法。要获取实现Operator接口的所有类,可以使用以下代码:

Reflections reflections = new Reflections("mypackage");
Set<Class<? extends Operator>> classes = reflections.getSubTypesOf(Operator.class);

希望你现在明白了。

答案 1 :(得分:0)

你可以使用工厂模式来实现这个如果你正在使用java 8那么String可以用作switch case的一部分否则你需要尝试char或int: -

public class MyFactory {
    private MyFactory() {
    }

    public static Operator getOperator(String operator) {
        switch (operator) {
            case "+":
                return new Plus();
            case "-":
                return new Minus();
            case "*":
                return new Multiply();
            case "/":
                return new Divide();
            case "%":
                return new Modulo();
        } 
    }
}

然后致电: -

Operator op = MyFactory.getOperator("+");
op.calculate(firstNumber,secondNumber);

答案 2 :(得分:0)

您可以使用URLClassLoader从给定文件夹动态加载类。请注意,您还需要以某种方式指定运算符名称。假设接口中有一个特殊的方法,如下所示:

public interface Operator
{
    String getOperator();

    double calculate(double firstNumber,double secondNumber);
}

你实现它是这样的:

public class Plus implements Operator
{   
    @Override
    public double calculate(double firstNumber,double secondNumber)
    {
        return firstNumber + secondNumber;
    }

    @Override
    public String getOperator() {
        return "+";
    }
}

然后你可以加载给定文件夹中的所有操作符,如下所示:

Map<String, Operator> initOperators(File folder) {
    File[] files = folder.listFiles();
    Map<String, Operator> operators = new HashMap<String, Operator>();
    if(files == null)
        return operators;
    URLClassLoader cl;
    try {
        cl = new URLClassLoader(new URL[] {folder.toURI().toURL()});
    } catch (MalformedURLException e) {
        return operators;
    }
    for(File file : files) {
        String name = file.getName();
        if(name.endsWith(".class")) {
            try {
                String className = name.substring(0, name.length()-".class".length());
                Operator op = cl.loadClass(className)
                                .asSubclass(Operator.class)
                                .newInstance();
                operators.put(op.getOperator(), op);
            } catch (ClassNotFoundException e) {
            } catch (InstantiationException e) {
            } catch (IllegalAccessException e) {
            } catch (ClassCastException e) {
            } catch (NoClassDefFoundError e) {
            }
        }
    }
    return operators;
}

在我的示例中,例外被忽略,您可能决定以更合适的方式处理它们。