2016-05-12 72 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 
    } 

}