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