2013-12-14 12 views
7

मैं सी # में प्रोग्राम हूं जिसे आप कमांड को नियंत्रित करके नियंत्रित करते हैं, इसलिए अब मेरे पास एक लंबा स्विच स्टेटमेंट है।रिएक्टर लंबे स्विच स्टेटमेंट

switch (command) 

{ 
    case "Show commands": 
     ProgramCommans.ShowAllCommands(); 
     break; 
    case "Close window": 
     ControlCommands.CloseWindow(); 
     break; 
    case "Switch window": 
     ControlCommands.SwitchWindow(); 
     break; 
} 

और इतने पर

लगभग सभी मामलों में केवल एक ही विधि कॉल की तरह कुछ, विधियों नहीं एक वर्ग में वे कई वर्गों में वितरित कर रहे हैं। तो सवाल यह है कि, मैं इस स्विच को और अधिक सुरुचिपूर्ण तरीके से कैसे प्रतिक्रिया दे सकता हूं?

+0

समान हस्ताक्षर वाले सभी कार्य हैं? – elyashiv

+0

यह http://codereview.stackexchange.com/ के लिए बेहतर अनुकूल हो सकता है। –

+1

जब भी आप स्वयं को कोड लिखते हैं जो एक विधि का प्रतिनिधित्व करने के लिए * स्ट्रिंग * का उपयोग करता है तो आपको सबसे पहले "प्रतिनिधि" को सोचना चाहिए। –

उत्तर

1

यदि सभी फ़ंक्शंस समान पैरामीटर प्राप्त करते हैं और एक ही मान वापस करते हैं, तो आप Dictionary के साथ delegates के साथ किसी फ़ंक्शन को स्ट्रिंग मैप करने के लिए उपयोग कर सकते हैं। यह विधि आपको स्विच समय में स्विच करने की अनुमति देगी - बाहरी कार्यक्रमों को प्रोग्राम की कार्यक्षमता बढ़ाने की इजाजत देता है।

कार्यों ही नहीं हैं, तो आप रैपर लिख सकता है - एक प्रॉक्सी समारोह है कि अन्य सभी कार्यों के रूप में मानकों को मिल जाएगा, और कार्यों आप चाहते हैं कहते हैं।

+1

और फिर _ "मैं अपना शब्दकोश-भरने कोड कैसे दोबारा कर सकता हूं" _ –

0

यहां आप यहां क्या कर सकते हैं। आप एक इंटरफेस [आईसीओएमएंड] बना सकते हैं जहां आप एक सामान्य कार्य कर सकते हैं [उदाहरण: निष्पादित करें]।

फिर आपको उस सदस्य को उचित प्रकार के साथ शुरू करने और निष्पादन फ़ंक्शन को कॉल करने की आवश्यकता है। इसमें भविष्य में और अधिक कार्य शामिल हो सकते हैं और इस प्रकार विस्तारित किया जा सकता है।

इसके अलावा, आप एक कारखाना विधि बना सकते हैं जहां आप पैरामीटर पास कर सकते हैं और उचित वर्ग के साथ काम करने के लिए प्राप्त कर सकते हैं।

उम्मीद है कि मदद करता है।

0

मुझे एहसास है कि यह एक पुरानी पोस्ट है, लेकिन इन स्थितियों में मुझे विशेषताओं और कारखाने को बहुत आसान लगता है।

निम्न कोड आपको एक कस्टम विशेषता (Command) का उपयोग करता है ताकि आप अपनी विधियों को विशेषता दे सकें, जिससे आपको यह पता चल सके कि उन्हें आपको कैसे जवाब देना चाहिए।

कारखाने विधि प्रतिबिंब का उपयोग करता है इन तरीकों में से एक शब्दकोश उत्पन्न करने के लिए है और यह कहता है कि जब भी आप CommandFactory कहते हैं।

हालात थोड़ा साफ कर सकता हो, आह्वान बुला एक छोटे बदसूरत है, लेकिन यह सिर्फ तुम कैसे कोड निष्पादित करने के लिए चाहते हैं पर निर्भर करता है।

using System.Collections.Generic; 
using System.Linq; 

namespace MyApp 
{ 
    using System.Reflection; 
    using MyApp.Commands; 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      var methods = new MyCommands(); 
      MethodInfo myMethod; 
      myMethod = CommandFactory.GetCommandMethod("Show Commands"); 
      myMethod.Invoke(methods, null); 
      myMethod = CommandFactory.GetCommandMethod("Close window"); 
      myMethod.Invoke(methods, null); 
      myMethod = CommandFactory.GetCommandMethod("Switch window"); 
      myMethod.Invoke(methods, null); 
     } 
    } 

    public static class CommandFactory 
    { 
     private static Dictionary<string, MethodInfo> speechMethods = new Dictionary<string, MethodInfo>(); 
     public static MethodInfo GetCommandMethod(string commandText) 
     { 
      MethodInfo methodInfo; 
      var commands = new MyCommands(); 
      if (speechMethods.Count == 0) 
      { 
       var methodNames = 
        typeof(MyCommands).GetMethods(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance); 
       var speechAttributeMethods = methodNames.Where(y => y.GetCustomAttributes().OfType<CommandAttribute>().Any()); 
       foreach (var speechAttributeMethod in speechAttributeMethods) 
       { 
        foreach (var attribute in speechAttributeMethod.GetCustomAttributes(true)) 
        { 
         speechMethods.Add(((CommandAttribute)attribute).Command, speechAttributeMethod); 
        } 
       } 
       methodInfo = speechMethods[commandText]; 
      } 
      else 
      { 
       methodInfo = speechMethods[commandText]; 
      } 
      return methodInfo; 
     } 
    } 
} 

namespace MyApp.Commands 
{ 
    class MyCommands 
    { 
     [Command("Show All")] 
     [Command("Show All Commands")] 
     [Command("Show commands")] 
     public void ShowAll() 
     { 
      ProgramCommands.ShowAllCommands(); 
     } 

     [Command("Close Window")] 
     public void CloseWindow() 
     { 
      ControlCommands.CloseWindow(); 
     } 

     [Command("Switch Window")] 
     public void SwitchWindow() 
     { 
      ControlCommands.SwitchWindow(); 
     } 
    } 

    [System.AttributeUsage(System.AttributeTargets.Method, AllowMultiple = true)] 
    public class CommandAttribute : System.Attribute 
    { 
     public string Command 
     { 
      get; 
      set; 
     } 

     public CommandAttribute(string textValue) 
     { 
      this.Command = textValue; 
     } 
    } 
} 
7

आप अपने स्विच बयान refactor करने के लिए ऐसा कर सकते हैं:

var commands = new Dictionary<string, Action>() 
{ 
    { "Show commands",() => ProgramCommans.ShowAllCommands() }, 
    { "Close window",() => ControlCommands.CloseWindow() }, 
    { "Switch window",() => ControlCommands.SwitchWindow() }, 
}; 

if (commands.ContainsKey(command)) 
{ 
    commands[command].Invoke(); 
} 

मुख्य लाभ यह इस दृष्टिकोण है कि आप रन-टाइम में "स्विच" बदल सकता है।

+0

यह एक महान और सरल दृष्टिकोण है। मुझे यह मेरी तुलना में बेहतर पसंद है। +1 – paqogomez

0

मुझे पता है कि जवाब थोड़ा देर हो गया है, SOLID सिद्धांत का दुरुपयोग नहीं करने के लिए, आप इंटरफ़ेस या विरासत का उपयोग कर सकते हैं। इस उदाहरण में, मैं विरासत का उपयोग करता हूं क्योंकि आपके पास "कमांड" स्ट्रिंग के अन्य उपयोग हो सकते हैं।

public abstract class commandRepository { 
    string command ; // if there is no usage in other function class, you can get rid of it 
    public abstract void DoCommands(); 
} 
public class ShowCommands:commandRepository 
{ 
    public ShowCommands(){ 
     command ="Show commands"; // if there is no usage in other function class, you can get rid of it 
    } 
    public override void DoCommands(){ 
     ProgramCommans.ShowAllCommands(); 
    } 
} 
public class CloseWindow:commandRepository 
{ 

    public CloseWindow(){ 
     command ="Close window"; // if there is no usage in other function class, you can get rid of it 
    } 
    public override void DoCommands(){ 
     ProgramCommans.CloseWindow(); 
    } 
} 
public class SwitchWindow:commandRepository 
{ 
    public SwitchWindow(){ 
     command ="Switch window"; // if there is no usage in other function class, you can get rid of it 
    } 
    public override void DoCommands(){ 
     ProgramCommans.SwitchWindow(); 
    } 
} 
संबंधित मुद्दे