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
2009-11-20 05:17:01
+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
2009-11-20 05:21:10
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
2009-11-20 05:23:06
actually reflection is a poor choice as it is a resource monster. Far too often I have seen fellow developers abuse reflection.
Woot4Moo
2009-11-20 05:27:26
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
2009-11-20 05:34:12
I added some updates to try help explain.
astander
2009-11-20 06:40:00
thanks a bunch buddy !!
redzedi
2009-11-20 09:10:00