Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 处理不同类型指令以进行不同类型方法调用的设计模式_Java_Oop_Design Patterns - Fatal编程技术网

Java 处理不同类型指令以进行不同类型方法调用的设计模式

Java 处理不同类型指令以进行不同类型方法调用的设计模式,java,oop,design-patterns,Java,Oop,Design Patterns,我在互联网上看到了许多线程,但我无法适应我的问题的任何模式 我想分析一条可以调用不同类型调用的指令。比如说, 例如,指令类型可以是type-1、type-2等,而被调用的方法可以是method1、method2等,因此存在一种多对多关系 instType1 method1 instType2 method1 instType2 method3 instType3 method3 ... 我已经考虑过每个指令类型和每个方法类型都有一个处理程序,但不管怎样,我都必须在每个处理程序中为另一个编写检

我在互联网上看到了许多线程,但我无法适应我的问题的任何模式

我想分析一条可以调用不同类型调用的指令。比如说,

例如,指令类型可以是type-1、type-2等,而被调用的方法可以是method1、method2等,因此存在一种多对多关系

instType1 method1
instType2 method1
instType2 method3
instType3 method3 
...
我已经考虑过每个指令类型和每个方法类型都有一个处理程序,但不管怎样,我都必须在每个处理程序中为另一个编写检查。例如,在instruction-type1-Handler中,我必须检查调用的类型是method1还是method2等

有什么简单或更干净的方法可以做到这一点吗

编辑-1

一个具体的例子是

invoke-virtual v7, v4, Ljava/io/FileOutputStream;->write
在这里,我可以有不同类型的invoke-*调用和不同的Java API调用集

我想为每个调用类型和被调用的API类型编写一个单独的处理程序。假设我给出这个指令来调用虚拟处理程序,它必须首先检查调用类型,然后处理它。每个处理程序中都有相同的逻辑


有什么方法可以避免在不同的处理程序中使用相同的代码吗?

这个方法可能适合您。尽管您需要编写更多的类,但这可能会产生一个更干净的全面体系结构(避免代码中分散的条件)。

我同意Kayaman的设计。尽管如此,我认为您知道还有另一种方法是很好的,通过Java的反射API。假设您希望能够执行以下操作:

evaluate(instruction, call);
无需在方法中使用评估(…)一整套开关如果ELSE。我建议使用Java的API反射,这意味着您可以添加任意多的指令和调用,而无需更改评估它们的代码(功能)(面向对象编程的核心原因)

希望我不会在下面的解释中失去你。让我们先声明指令调用抽象类

public abstract class Call {
String name;

public Call(String name){
    this.name=name;
}

public String evaluate(){
    return this.name;
}

 }

public abstract class Instruction {
String name;

public Instruction(String name){
    this.name=name;
}

public String evaluate(){
    return this.name;
}   
}
我放置了非常基本的功能,只是为了确保它能正常工作。现在,让我们创建两个不同的类,它们从指令和调用扩展而来,这样我们就可以玩一些东西了

public class Instruction1 extends Instruction {

public Instruction1(String name) {
    super(name);
}

}

public class Call1 extends Call {

public Call1(String name) {
    super(name);
}

}
我不会发布所有的类,因为它的代码与指令1和调用1相同。所以我创建的类是:Instruction1,Instruction2,Instruction3,Call1,Call2,Call3。

现在我们有了它,我们将创建一个类,负责处理组合(指令,调用)的正确调用。你的评估者,如果你愿意的话

public class InstructionCallsEvaluator {
public String evaluate(Instruction1 instruction, Call1 call){
    return this.evaluate( (Instruction) instruction, (Call) call);
}

public String evaluate(Instruction1 instruction, Call2 call){
    return this.evaluate( (Instruction) instruction, (Call) call);
}

public String evaluate(Instruction1 instruction, Call3 call){
    return this.evaluate( (Instruction) instruction, (Call) call);
}

public String evaluate(Instruction2 instruction, Call1 call){
    return this.evaluate( (Instruction) instruction, (Call) call);
}

public String evaluate(Instruction2 instruction, Call2 call){
    return this.evaluate( (Instruction) instruction, (Call) call);
}

public String evaluate(Instruction2 instruction, Call3 call){
    return this.evaluate( (Instruction) instruction, (Call) call);
}

public String evaluate(Instruction3 instruction, Call1 call){
    return this.evaluate( (Instruction) instruction, (Call) call);
}

public String evaluate(Instruction3 instruction, Call2 call){
    return this.evaluate( (Instruction) instruction, (Call) call);
}

public String evaluate(Instruction3 instruction, Call3 call){
    return this.evaluate( (Instruction) instruction, (Call) call);
}

private String evaluate(Instruction instruction, Call call){
    return instruction.evaluate() + "  " + call.evaluate();
}
}
public class InstructionHandler {

public String evaluate(Instruction instruction, Call call) {
    try {
        return  useEvaluator(InstructionCallsEvaluator.class, instruction, call);
    } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | 
             InvocationTargetException | NoSuchMethodException ex) {
        Logger.getLogger(InstructionHandler.class.getName()).log(Level.SEVERE, null, ex);
    }
    return "Something went wrong when calling Evaluator";
}


private String useEvaluator(Class<InstructionCallsEvaluator> instructionCallsEvalutor, Instruction instruction, Call call) 
                    throws InstantiationException, IllegalAccessException, IllegalArgumentException, 
                    InvocationTargetException, NoSuchMethodException {    
    Class[] methodParameterTypes = new Class[]{instruction.getClass(), call.getClass()};
    Object instance = instructionCallsEvalutor.newInstance();
    Method method = instructionCallsEvalutor.getDeclaredMethod("evaluate", methodParameterTypes);
    return  method.invoke(instance, instruction, call).toString();
}
很长时间了吧?在这里,您可以添加所有可能的组合。因此,如果您要添加一个新类#,您必须来到这个评估器并添加相应的组合。如果与命令模式实现相比,您可以认为这是一个缺点

我之所以添加了
私有字符串evaluate(指令,调用)
,是因为如果输出的格式发生了变化,我只需要改变这个方法,而不需要改变所有其他方法

另外,我之所以在调用此方法之前向上转换方法参数,是因为如果不这样,您将得到一个永无止境的循环,从而导致stackOverflow异常:

public String evaluate(Instruction3 instruction, Call1 call){
    return this.evaluate(instruction, call);
}
如果我让它像这样执行,当它调用this.evaluate(…)时,它将在一个永无止境的循环中调用
公共字符串evaluate(指令3指令,调用1调用)

我之所以展示这种实现方式,是因为我假设出于某种原因,您希望确定调用指令的组合是什么。否则,我将使用命令模式。

显然,我在evaluate(…)**中所做的工作非常简单,因为我不知道您想要做什么。你必须适应你的情况

既然处理程序已经设置好了,那么让我们来看一个类,该类负责在不使用if elses开关的情况下正确调用它。你的主人,如果你愿意的话

public class InstructionCallsEvaluator {
public String evaluate(Instruction1 instruction, Call1 call){
    return this.evaluate( (Instruction) instruction, (Call) call);
}

public String evaluate(Instruction1 instruction, Call2 call){
    return this.evaluate( (Instruction) instruction, (Call) call);
}

public String evaluate(Instruction1 instruction, Call3 call){
    return this.evaluate( (Instruction) instruction, (Call) call);
}

public String evaluate(Instruction2 instruction, Call1 call){
    return this.evaluate( (Instruction) instruction, (Call) call);
}

public String evaluate(Instruction2 instruction, Call2 call){
    return this.evaluate( (Instruction) instruction, (Call) call);
}

public String evaluate(Instruction2 instruction, Call3 call){
    return this.evaluate( (Instruction) instruction, (Call) call);
}

public String evaluate(Instruction3 instruction, Call1 call){
    return this.evaluate( (Instruction) instruction, (Call) call);
}

public String evaluate(Instruction3 instruction, Call2 call){
    return this.evaluate( (Instruction) instruction, (Call) call);
}

public String evaluate(Instruction3 instruction, Call3 call){
    return this.evaluate( (Instruction) instruction, (Call) call);
}

private String evaluate(Instruction instruction, Call call){
    return instruction.evaluate() + "  " + call.evaluate();
}
}
public class InstructionHandler {

public String evaluate(Instruction instruction, Call call) {
    try {
        return  useEvaluator(InstructionCallsEvaluator.class, instruction, call);
    } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | 
             InvocationTargetException | NoSuchMethodException ex) {
        Logger.getLogger(InstructionHandler.class.getName()).log(Level.SEVERE, null, ex);
    }
    return "Something went wrong when calling Evaluator";
}


private String useEvaluator(Class<InstructionCallsEvaluator> instructionCallsEvalutor, Instruction instruction, Call call) 
                    throws InstantiationException, IllegalAccessException, IllegalArgumentException, 
                    InvocationTargetException, NoSuchMethodException {    
    Class[] methodParameterTypes = new Class[]{instruction.getClass(), call.getClass()};
    Object instance = instructionCallsEvalutor.newInstance();
    Method method = instructionCallsEvalutor.getDeclaredMethod("evaluate", methodParameterTypes);
    return  method.invoke(instance, instruction, call).toString();
}
它将抽象类作为参数。一旦进入,它必须调用类的相应的evaluate(…)方法指令callsevaluator。我之所以将其分为两种方法,是为了将
try{}catch{}
放在其中一种方法中,而将实际方法放在另一种方法中(干净性和可读性)

您已经知道要调用其方法的类: 指令CallSeValuator,但您不知道要调用哪个方法。那就是

专用字符串使用计算器(类指令调用计算器、指令指令、调用)

进来

此方法处理methodParameterTypes,创建InstructionCallsEvaluator类的实例,并确定应用于传递的参数的方法。一旦获得了该方法,它就会简单地调用它。让我们尝试一下这个主要类:

public class Main {

public static void main(String[] args) {
    ArrayList<Instruction> instructions = getInstructions();
    ArrayList<Call> calls = getCalls();
    InstructionHandler handler = new InstructionHandler();

    for(Instruction instrct : instructions)
        for(Call call : calls)
            System.out.println(handler.evaluate(instrct, call));
}

private static ArrayList<Instruction> getInstructions(){
    ArrayList<Instruction> instructions = new ArrayList<>();
    instructions.add(new Instruction1("Instruction 1"));
    instructions.add(new Instruction2("Instruction 2"));
    instructions.add(new Instruction3("Instruction 3"));
    return instructions;
}

private static ArrayList<Call> getCalls(){
    ArrayList<Call> calls = new ArrayList<>();
    calls.add(new Call1("Call 1"));
    calls.add(new Call2("Call 2"));
    calls.add(new Call3("Call 3"));
    return calls;
}
你可能会想,为什么我不干脆跳过整个指令处理程序课程,选择:

指令CallSeValuator evaluator=新指令CallSeValuator(); 评估者。评估者(……)

那是因为那时我必须手动调用
evaluator.evalute(…),这样我的main将如下所示:

   evaluator.evalute(new Instruction1(), new Call1());
   evaluator.evalute(new Instruction2(), new Call2());
   ...
而不是能够称之为传递它为所述类的向上传播。当然,这取决于你的目标是什么,你可能只是想要这个,在这种情况下,你可以跳过说明ha
    private String evaluate(Instruction instruction, Call call){
    return instruction.evaluate() + "  " + call.evaluate();
}