views:

62

answers:

4

say you have to interpret a sting of command arguments like AABBCDEEFF... and the idea is that each character represents a command for which you have to take some actions on the class, the ugly solution is to write a big switch-case but i dont want to use that , can anybody suggest a more elegant solution ??

+1  A: 

Well my suggestion is switch, as the compiler will optimize it for you. How many potential characters are there that will occur?

Woot4Moo
+2  A: 

Make everything as simple as possible. Stay with the SWITCH.

davidrobles
+4  A: 

Create a map of methods like: map<char, func_ptr>, then fill it with your "actions":

act_map['A'] = &my_class::func_a
....

and

for each c in str
  arc_map[c]()

Real implementation depends of your language.

But if you have up to 5-10 actions than just use switch.

Elalfer
A: 

For C#, In the more complex case a solution can be to implement and interface, or add attributes and use reflection to call the command or method.

OK, as an example i created some C# code

public class ExecuteSequence
    {
        Dictionary<string, Type> classes = new Dictionary<string, Type>();
        public void LoadClasses()
        {
            classes.Clear();
            //load all classes with attribute
            //this can be done at startup once, or on requested refresh
            foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
                foreach (Type type in assembly.GetTypes())
                    foreach (object attribute in type.GetCustomAttributes(typeof(MethodAttribute), true))
                        if (attribute.GetType() == typeof(MethodAttribute))
                            classes.Add(((MethodAttribute)attribute).MethodName, type);
        }

        public string Execute(string sequence)
        {
            string retVal = "";
            foreach (char c in sequence)
                if (classes.ContainsKey(c.ToString()))
                {
                    IMethod method = (IMethod)Activator.CreateInstance(classes[c.ToString()]);
                    retVal += method.Execute();
                }

            return retVal;
        }
    }

    public class MethodAttribute : Attribute
    {
        private readonly string m_MethodName;
        public MethodAttribute(string methodName)
        {
            m_MethodName = methodName;
        }
        public string MethodName
        {
            get { return m_MethodName; }
        }
    }
    public interface IMethod
    {
        string Execute();
    }

    [Method("A")]
    public class MethodA : IMethod
    {
        public string Execute()
        {
            return "FOO";
        }
    }

    [Method("B")]
    public class MethodB : IMethod
    {
        public string Execute()
        {
            return "BAR";
        }
    }

You can limit the list of initial assemblies scanned, but as mentioned, this should only load on startup.

Hope this helps.

astander
actually reflection is a poor choice as it is a resource monster. Far too often I have seen fellow developers abuse reflection.
Woot4Moo
hi can you elaborate on this a little more ?? i am thinking of something in conjunction with Elalfer's response above that like may be we can have a map of command objects with a facility to register them dynamically then my interpretation module just has to look of for the current token in that map and call execute().Unlike a standard command pattern my receiver is gonna be fixed and it has to be injected by the context on the command class.So different interpretations of the command class are actually variations of invocation on the same receiver class.Do you think i am in the right way ??
redzedi
I added some updates to try help explain.
astander
thanks a bunch buddy !!
redzedi