2016-05-12 52 views
4

考虑的方法爪哇 - 方法依赖于实现从参数值

public void doSomething(String actionID){ 
switch (actionID){ 
    case "dance": 
      System.out.print("I'm dancing"); 
      break; 
    case "sleep": 
      System.out.print("I'm sleeping"); 
      break; 
    default: 
      System.out.print("I've no idea what I'm doing"); 
} 

方法的实现依赖于参数的值。有没有更好的方法来做到这一点,或者有不同的设计模式来复制行为?

+0

可能是可能是你正在寻找这样的事情? http://crunchify.com/why-and-for-what-should-i-use-enum-java-enum-examples/ –

+4

你可以实现一个命令模式。 –

回答

0

以下是基于示例问题的命令模式的简单实现。我定义了一个包含两种方法的抽象类AbstractCommand。第一种方法createCommand()根据输入的字符串名称实例化一个命令类。这就是你可以委托你的字符串输入来创建正确类型的命令。第二种方法是doAction(),这是未定义的,稍后将由具体的具体命令类实现。

public abstract class AbstractCommand { 
    public static AbstractCommand createCommand(String name) { 
     try { 
      String clsName = name + "Command"; 
      Class<?> cls = Class.forName(clsName); 
      AbstractCommand command = (AbstractCommand) cls.newInstance(); 

      return command; 
     } 
     catch (Exception e) { 
      System.out.println("Something went wrong."); 
     } 
    } 

    public abstract void doAction(); 
} 

public class DanceCommand extends AbstractCommand { 
    public void doAction() { 
     System.out.println("I'm dancing"); 
    } 
} 

public class TestCommandPattern { 
    public void doSomething(String actionID) { 
     AbstractCommand cmd = AbstractCommand.createCommand(actionID); 
     cmd.doAction(); 
    } 

    public static void main(String[] args) { 
     TestCommandPattern test = new TestCommandPattern(); 
     test.doSomething("Dance"); // should print "I'm dancing" 
    } 
} 

既然已经设置好了这个框架,那么您可以轻松地为原始问题中的各种类型的操作添加其他命令。例如,您可以创建一个SleepCommand类,该类将输出I'm sleeping,或者执行您希望的任何操作。

4

如果呼叫者决定是通过将​​不同的字符串执行什么逻辑,那么为什么不只是叫他们不同的方法:

public void doSomething(String actionID) {...} 
... 
doSomething("dance"); 
doSomething("sleep"); 

VS:

public void dance() {...} 
public void sleep() {...} 
... 
dance(); 
sleep(); 

好像你不必要地将所有呼叫汇入doSomething


但字符串可能并不总是文字。如果你从控制台拿走他们会怎么样?

你可以到相应的功能,提供了从字符串的静态映射:

class MyClass { 
    private static final Map<String, Consumer<MyClass>> map = new HashMap<>(); 

    static { 
     map.put("sleep", MyClass::sleep); 
     map.put("dance", MyClass::dance); 
    } 

    public void doSomething(String actionID) { 
     map.getOrDefault(actionID, MyClass::doNothing).accept(this); 
    } 

    public void dance() { 
     System.out.print("I'm dancing"); 
    } 

    public void sleep() { 
     System.out.print("I'm sleeping"); 
    } 

    private void doNothing() { 
     System.out.println("I've no idea what I'm doing"); 
    } 
} 

这使得在那里你有很多的开关情况下,很多清洁方案。

1

介绍一个接口,例如,

public interface HumanState { 

    public void tellMeWhatYouAreDoing(); 
    } 

封装逻辑在不同的实现

public class DancingState implements HumanState { 
    @Override 
    public void tellMeWhatYouAreDoing() { 
     System.out.println("I'm dancing"); 
    } 
    } 

    public class SleepingState implements HumanState { 

    @Override 
    public void tellMeWhatYouAreDoing() { 
     System.out.println("I'm sleeping"); 
    } 
    } 

    public class UnknownState implements HumanState { 

    @Override 
    public void tellMeWhatYouAreDoing() { 
     System.out.println("I've no idea what I'm doing"); 
    } 
    } 

和使用的地图。例如。

public class HumanStateExample { 

    public static void main(String[] args) { 
    HumanStateExample humanStateExample = new HumanStateExample(); 

    humanStateExample.doSomething("dance"); 
    humanStateExample.doSomething("sleep"); 
    humanStateExample.doSomething("unknown"); 
    } 

    private final HashMap<String, HumanState> humanStateMap; 


    public HumanStateExample(){ 
    humanStateMap = new HashMap<String, HumanState>(); 
    humanStateMap.put("dance", new DancingState()); 
    humanStateMap.put("sleep", new SleepingState()); 

    } 

    public void doSomething(String action) { 
    HumanState humanState = humanStateMap.get(action); 
    if(humanState == null){ 
     humanState = new UnknownState(); 
    } 

    humanState.tellMeWhatYouAreDoing(); 
    } 
} 
1

我不知道的格局是怎么叫的,但如果你需要基于一个以上的参数委托方法调用它是非常有用:

创造了很多的处理程序,其中每一个知道它何时负责处理呼叫。然后循环遍历它们并调用与该参数匹配的第一个。

编辑:我改名类从FancyParameterAction 到FancyParameterAction 实用:它不是一个工厂,这个名字被误导

//Your method, but this time with a complex object, not with a simple string. 
public void doSomething(FancyParameterObject fpo){ 
    FancyParameterActionUtility.invokeOn(fpo); 
} 


//The utility which can handle the complex object and decides what to do. 
public class FancyParameterActionUtility{ 
    public Interface FPAHandler{ 
     void invoke(FancyParameterObject fpo); 
     boolean handles(FancyParameterObject fpo); 
    } 

    //Omitted: Different implementations of FPAHandler 

    public static List<FPAHandler> handlers = new LinkedList<>(); 

    static{ 
     handlers.add(new DanceHandler()); 
     handlers.add(new SleepHandler()); 
     //Omitted: Different implementations of FPAHandler 
    } 

    public static void invokeOn(FancyParameterObject fpo){ 
     for(FPAHandler handler:handlers){ 
      if (handler.handles(fpo)){ 
       handler.invoke(fpo); 
       return; 
      } 
     } 
     //Default-Behavior 
    } 

}