Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/323.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/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_Design Patterns - Fatal编程技术网

Java 处理基于条件的方法调用的最佳设计

Java 处理基于条件的方法调用的最佳设计,java,design-patterns,Java,Design Patterns,处理基于条件的方法调用的最佳设计模式是什么?条件基于字符串比较。我知道basic if-else或switch可以解决这个问题,但仍在寻找其他解决方案 示例: 用户按顺序输入字符串foo1、foo2和foo3。现在程序根据这些输入调用一个方法,即: if (input.equals("foo1")) fun1(); else if(input.equals("foo2")) fun2(); 等等 另外,fun1()和fun2()的功能是完全独立的。这取决于它们。在你的情况下,没有一

处理基于条件的方法调用的最佳设计模式是什么?条件基于字符串比较。我知道basic if-else或switch可以解决这个问题,但仍在寻找其他解决方案

示例:

用户按顺序输入字符串
foo1
foo2
foo3
。现在程序根据这些输入调用一个方法,即:

if (input.equals("foo1"))
   fun1();
else if(input.equals("foo2"))
   fun2();
等等


另外,
fun1()
fun2()
的功能是完全独立的。

这取决于它们。在你的情况下,没有一个。但通常您会通过某种形式的多态性或模板方法模式来解决这个问题。但您的数据模型似乎并没有以这种方式设计,所以您几乎完蛋了,您将不得不创建一个丑陋的嵌套IF结构。或者,您可以稍微重构它,并使用模板方法模式。在这种情况下,您可以使用工厂方法模式根据字符串创建不同的模板,这些模板中的每一个都有一个不同的
TemplateMethod()
,将被调用。这允许您平等地对待所有对象,但有一个部分(模板方法)可以独立操作

有关更深入的说明,请参见:

编辑:添加了不那么糟糕的工厂方法的示例

TemplateFactory.java

public class TemplateFactory {
    private Map<String, Class> map;

    public TemplateFactory() {
        this.map = new TreeMap<>();
        map.put("Template 1", Template1.class);
        map.put("Template 2", Template2.class);
    }

    public BaseTemplate createBaseTemplate(String comparison)
    {
        if (!map.containsKey(comparison))
        {
            return null;
        }
        try {
            return (BaseTemplate) map.get(comparison).getConstructor().newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) {
        TemplateFactory tf = new TemplateFactory();
        BaseTemplate t1 = tf.createBaseTemplate("Template 1");
        BaseTemplate t2 = tf.createBaseTemplate("Template 2");
        System.out.println(t1.templateMethod(""));
        System.out.println(t2.templateMethod(""));
    }
}
Template1.java

public class Template1 extends BaseTemplate {
    @Override
    public String templateMethod(String data) {
        return "Template 1";
    }
}
模板2.java

public class Template1 extends BaseTemplate {
    @Override
    public String templateMethod(String data) {
        return "Template 2";
    }
}

在您的情况下,我将考虑代码< > EnUM <代码>和Twitter case < /代码>的组合。我们不应为此使用字符串的原因是:

  • 如果您使用拼写错误的字符串来调用函数(
    getFunction(“foO”)
    ,而不是
    getFunction(“foO”)
    ),您不知道如何调试它,编译器不会告诉您任何事情

  • 如果您错误地使用了两个相同的字符串来引用两个不同的方法,那么您也无法检测到它

  • 您不能遍历所有字符串,
    enum
    有一个
    values()
    方法用于该操作

所以我的建议是使用
enum

public enum Function{
  foo1,
  foo2;
} 

您可以使用Runnables而不是factory来简化它:

public class Router {
    private Map<String, Class> map;

    public Router() {
        this.map = new HashMap<>();
        map.put("foo1", new Runnable(){
            run(){
                fun1();
            }
        });
        map.put("foo2", new Runnable(){
            run(){
                fun2();
            }
        });
    }

    public void doRoot(String command) throws IllegalArgumentException {
        Runnable r = map.get(command);
        if(r == null){
            throw new IllegalArgumentException("invalid command: " + command);
        }
        r.run();
    }

    fun1(){}

    fun2(){}

}
公共类路由器{
私人地图;
公共路由器(){
this.map=新的HashMap();
map.put(“foo1”,新的Runnable(){
运行(){
fun1();
}
});
map.put(“foo2”,新的Runnable(){
运行(){
fun2();
}
});
}
public void doRoot(String命令)引发IllegalArgumentException{
Runnable r=map.get(命令);
if(r==null){
抛出新的IllegalArgumentException(“无效命令:”+命令);
}
r、 run();
}
fun1(){}
fun2(){}
}

您能提供更多详细信息吗<代码>条件基于字符串比较?请举例说明这个问题太宽泛了。根据需要,你可以考虑使用有限状态机或其他技术。仅方法名就足够了吗?用字符串引用方法对我来说是双倍的工作量。即使工厂模式也使用丑陋的if-else-if结构(只是一个简单的示例shape工厂类)。现在想象成百上千种不同的形状(圆形、正方形、五角大楼……等等),这个shapefactory类看起来会很糟糕。我只是在寻找更好的方法,不一定。这是个糟糕的例子。一个更好的例子是在工厂中保留一个“Map”,然后查找所需的类,或者从IoC容器中将其作为依赖项获取,或者只是创建一个新实例。@avenger我已更新了我的答案,以包含一个详细说明我答案的示例。理想情况下,您应该使用IoC容器(如Spring BeanFactory或Guice Injector)来创建和处理对象生命周期,而不是使用反射。但设置它有点超出了问题的范围。另外@PhamTrung也正确,您应该在字符串值上使用类型安全枚举器。
public class Router {
    private Map<String, Class> map;

    public Router() {
        this.map = new HashMap<>();
        map.put("foo1", new Runnable(){
            run(){
                fun1();
            }
        });
        map.put("foo2", new Runnable(){
            run(){
                fun2();
            }
        });
    }

    public void doRoot(String command) throws IllegalArgumentException {
        Runnable r = map.get(command);
        if(r == null){
            throw new IllegalArgumentException("invalid command: " + command);
        }
        r.run();
    }

    fun1(){}

    fun2(){}

}