【问题标题】:Dynamic program for handle operator手柄操作员动态程序
【发布时间】:2015-11-17 10:05:20
【问题描述】:

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

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 文件放在我的文件夹中,我的程序仍然应该工作(地图实现必须更改) 谁能帮我? 我很感激。

【问题讨论】:

  • 您的问题是什么?您的代码看起来不错,并且您描述的与其他运营商的类文件中的人一起使用的设置听起来也不错。
  • 可能是因为老师写了那部分 - 他在真正自己做某事时迷失了。
  • @Tim Biegeleisen 想象我实现了 %(我的程序不支持 %)并为 % 编译我自己的代码并将 .class 文件放在我的文件夹中(其他 .class 文件也在这个文件夹中)我的.class 文件中的程序应确定应选择哪个运算符
  • 所以你的意思是你将为 new 运算符创建一个新类,程序应该自动选择它。对吗?
  • @Tarun Gupta 是的。我将 Operator(Plus.Minus,Divide,Multiply) 的最后一个实现放入 myfolder(.class 文件) 现在我实现 % 并将 .class 也放入 myfolder 我的程序应该动态选择了正确的运算符(应该删除对 Map 的依赖)

标签: java


【解决方案1】:

您可以使用工厂模式来实现这一点如果您使用的是 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);

【讨论】:

  • @Rahul Yadav 我使用 java 6 .Sry 在你的程序依赖中也存在。我的程序应该自动选择最好的 .class
【解决方案2】:

您可以使用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;
}

在我的示例中只是忽略了异常,您可以决定以更合适的方式处理它们。

【讨论】:

  • 非常感谢。你的回答给了我一个新的想法。
【解决方案3】:

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

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

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 符号并将其与传递给此方法的运算符参数进行比较,如果符号与运算符匹配,将操作数传递给 Operator.calculate() 方法。要获取所有实现 Operator 接口的类,您可以使用以下代码:

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

希望你现在明白了。

【讨论】:

  • 是否用反射依赖来Map remove?
  • 是的,要删除对映射的依赖,您可以按照这种方法,还在您的操作员界面中添加一个新方法
  • @Tarun Gupta 非常感谢您的帮助。非常感谢
  • 好的,如果什么时候能够使它工作,请接受答案。
  • @Tarun Gupta Sry 我怎样才能接受答案?我是stackoverflow的新手
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-24
  • 1970-01-01
  • 2022-12-18
  • 1970-01-01
  • 2013-09-14
相关资源
最近更新 更多