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

时间:2014-05-02 07:40:52

标签: java design-patterns

处理基于条件的方法调用有哪些最佳设计模式?条件基于字符串比较。我知道基本的if-else-if或switch可以解决它但仍在寻找其他解决方案。

示例:

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

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

等等。

此外,fun1()fun2()的功能完全相互独立。

3 个答案:

答案 0 :(得分:0)

这取决于。在你的情况下,没有一个。但通常你会通过某种形式的多态或模板方法模式来解决这个问题。但是你的数据模型似乎并没有以这种方式设计,所以你几乎搞砸了,而且你必须制作一个丑陋的嵌套IF结构。或者,您可以稍微重构它并使用模板方法模式。在这种情况下,您可以使用Factory方法模式基于String创建不同的模板,这些模板中的每一个都将具有将被调用的不同TemplateMethod()。这允许您平等对待所有对象,但有一个部分(模板方法)独立行动。

有关更深入的说明,请参阅:http://en.wikipedia.org/wiki/Template_method_pattern

编辑:添加了一些不太蹩脚的Factory方法的示例。

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(""));
    }
}

BaseTemplate.java

public abstract class BaseTemplate {
    public String doSomething()
    {
        // whatever
        return "Hello";
    }

    public int anotherRealMethod(String data)
    {
        //also whatever
        return 0;
    }

    public abstract String templateMethod(String data);
}

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";
    }
}

答案 1 :(得分:0)

在您的情况下,我会考虑enumswitch case的组合。我们不应该使用字符串的原因是:

  • 如果你使用拼写错误的字符串来调用你的函数(getFunction("foO")而不是getFuntion("foo")),你就不知道如何调试它,编译器不会告诉你你什么。

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

  • 您无法遍历所有字符串,enumvalues()方法。

所以我的建议是使用enum

public enum Function{
  foo1,
  foo2;
} 

答案 2 :(得分:0)

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

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(){}

}