Command Pattern Implementation [modified]
-
Hi Guys, I've been working on a system for a while now, and it initially started off with a handful of functions that could be applied to it. This increased over time to around, and i split them up and put related functions into appropriate classes. These classes are now exhibiting the same problem i had initially with 100 methods in the same class. (Messy and poor cohesion) * I Have a set of low level classes that expose all the fine grain detail. * I have a set of high level classes that contain complex functions that manipulate the low level classes. * The high level functions are largely simple [void Function()]. Some with a few Private utility methods. * The high level functions generally do not call one another in the same class. * The high level functions DO call one another in different classes. * All High level function calls are made through a HUGE case statement atm, that is wrapped in a Logging exception handler. Many of these functions are invoked from Menu or Hotkeys or other argument free events such as Button press. I get the impression that this lends itself to a Command Pattern, but while i understand the concept, i can't get my head around how to implement it. (Factory? Pre-loaded Command Dictionary?) Also, how would i go about implementing a Command Tree? i.e. where one command calls another, and so on and so forth? And would this be a reasonable thing to do? Any Ideas? Cheers Tris
------------------------------- Carrier Bags - 21st Century Tumbleweed.
modified on Friday, May 16, 2008 11:35 AM
-
Hi Guys, I've been working on a system for a while now, and it initially started off with a handful of functions that could be applied to it. This increased over time to around, and i split them up and put related functions into appropriate classes. These classes are now exhibiting the same problem i had initially with 100 methods in the same class. (Messy and poor cohesion) * I Have a set of low level classes that expose all the fine grain detail. * I have a set of high level classes that contain complex functions that manipulate the low level classes. * The high level functions are largely simple [void Function()]. Some with a few Private utility methods. * The high level functions generally do not call one another in the same class. * The high level functions DO call one another in different classes. * All High level function calls are made through a HUGE case statement atm, that is wrapped in a Logging exception handler. Many of these functions are invoked from Menu or Hotkeys or other argument free events such as Button press. I get the impression that this lends itself to a Command Pattern, but while i understand the concept, i can't get my head around how to implement it. (Factory? Pre-loaded Command Dictionary?) Also, how would i go about implementing a Command Tree? i.e. where one command calls another, and so on and so forth? And would this be a reasonable thing to do? Any Ideas? Cheers Tris
------------------------------- Carrier Bags - 21st Century Tumbleweed.
modified on Friday, May 16, 2008 11:35 AM
Tristan Rhodes wrote:
Also, how would i go about implementing a Command Tree? i.e. where one command calls another, and so on and so forth? And would this be a reasonable thing to do?
From my memory I think I used Observable Pattern rather than a tree. It is also possible factories were involved.
led mike
-
Tristan Rhodes wrote:
Also, how would i go about implementing a Command Tree? i.e. where one command calls another, and so on and so forth? And would this be a reasonable thing to do?
From my memory I think I used Observable Pattern rather than a tree. It is also possible factories were involved.
led mike
Hi Mike, Thanks for the reply. I do have a number of observable components in the application and their events are handled in a centralized controller class. This class then runs the appropriate command / functionality. (Yes i do have a factory in there as well somewhere, but it's not related to the Command chain :) ) My concern is what to do to manage this large collection of functions and what options are available. Does the Command Pattern seem to be the way to go with this? While i am familiar with the pattern, i'm somewhat perplexed as to how to fit it into the application. I'm not interested in commands for the purpose of Undo / Redo which is the only implementation i am familiar with. Any further advice? Cheers Tris
------------------------------- Carrier Bags - 21st Century Tumbleweed.
-
Hi Mike, Thanks for the reply. I do have a number of observable components in the application and their events are handled in a centralized controller class. This class then runs the appropriate command / functionality. (Yes i do have a factory in there as well somewhere, but it's not related to the Command chain :) ) My concern is what to do to manage this large collection of functions and what options are available. Does the Command Pattern seem to be the way to go with this? While i am familiar with the pattern, i'm somewhat perplexed as to how to fit it into the application. I'm not interested in commands for the purpose of Undo / Redo which is the only implementation i am familiar with. Any further advice? Cheers Tris
------------------------------- Carrier Bags - 21st Century Tumbleweed.
Tristan Rhodes wrote:
I'm not interested in commands for the purpose of Undo / Redo which is the only implementation i am familiar with.
Not sure how to help you here. The implementation of a specific command like Undo/Redo have nothing to do with the Command Pattern. Probably the most significant benefit of the pattern is the isolation of the implementation of the commands from the implementation of the invokers. If that would be helpful to your project then you should consider using it, however:
Tristan Rhodes wrote:
I do have a number of observable components in the application and their events are handled in a centralized controller class. This class then runs the appropriate command / functionality.
That sounds like you have already centralized the implementation of your commands. Sometime interpreting design from someone else's point of view presented in text messages is not easy.
led mike
-
Tristan Rhodes wrote:
I'm not interested in commands for the purpose of Undo / Redo which is the only implementation i am familiar with.
Not sure how to help you here. The implementation of a specific command like Undo/Redo have nothing to do with the Command Pattern. Probably the most significant benefit of the pattern is the isolation of the implementation of the commands from the implementation of the invokers. If that would be helpful to your project then you should consider using it, however:
Tristan Rhodes wrote:
I do have a number of observable components in the application and their events are handled in a centralized controller class. This class then runs the appropriate command / functionality.
That sounds like you have already centralized the implementation of your commands. Sometime interpreting design from someone else's point of view presented in text messages is not easy.
led mike
Need a UML comment type. :D
------------------------------- Carrier Bags - 21st Century Tumbleweed.
-
Tristan Rhodes wrote:
I'm not interested in commands for the purpose of Undo / Redo which is the only implementation i am familiar with.
Not sure how to help you here. The implementation of a specific command like Undo/Redo have nothing to do with the Command Pattern. Probably the most significant benefit of the pattern is the isolation of the implementation of the commands from the implementation of the invokers. If that would be helpful to your project then you should consider using it, however:
Tristan Rhodes wrote:
I do have a number of observable components in the application and their events are handled in a centralized controller class. This class then runs the appropriate command / functionality.
That sounds like you have already centralized the implementation of your commands. Sometime interpreting design from someone else's point of view presented in text messages is not easy.
led mike
I did experiment with Commands a while back, but found myself doing lots of this:
ICommandExecutor cmd;
switch (cmdName)
{
case "DeleteCurrentSite":
cmd = new DeleteCurrentSiteCmd(container);case "AddNewSite": cmd = new AddSiteCmd(container); //.... lots more
}
cmd.Execute();
Which didn't solve the problem of my Mammoth case statement, nor did it provide a convenient solution for the Commands calling Commands problem. It felt like i was going in the right direction, but i got lost and had to backtrack. Does that seem reasonable? Cheers Tris
------------------------------- Carrier Bags - 21st Century Tumbleweed.
-
I did experiment with Commands a while back, but found myself doing lots of this:
ICommandExecutor cmd;
switch (cmdName)
{
case "DeleteCurrentSite":
cmd = new DeleteCurrentSiteCmd(container);case "AddNewSite": cmd = new AddSiteCmd(container); //.... lots more
}
cmd.Execute();
Which didn't solve the problem of my Mammoth case statement, nor did it provide a convenient solution for the Commands calling Commands problem. It felt like i was going in the right direction, but i got lost and had to backtrack. Does that seem reasonable? Cheers Tris
------------------------------- Carrier Bags - 21st Century Tumbleweed.
-
Tristan Rhodes wrote:
Does that seem reasonable?
using a switch statement? Almost never. Commands should be stored in a Map or Dictionary.
led mike
Bingo! Thankyou, that's exactly what i've been angling for. So, something like:
public ICommandExecutor GetCommand(string name)
{
if (_cmdDictionary.ContainsKey(name) == false)
_cmdDictionary.Add(name, _commandFactory.GetCommand(name));return \_cmdDictionary\[name\];
}
What would you have to do to handle commands which have parameters? Or would that be a symptom of bad design? Cheers! Tris
------------------------------- Carrier Bags - 21st Century Tumbleweed.
-
Bingo! Thankyou, that's exactly what i've been angling for. So, something like:
public ICommandExecutor GetCommand(string name)
{
if (_cmdDictionary.ContainsKey(name) == false)
_cmdDictionary.Add(name, _commandFactory.GetCommand(name));return \_cmdDictionary\[name\];
}
What would you have to do to handle commands which have parameters? Or would that be a symptom of bad design? Cheers! Tris
------------------------------- Carrier Bags - 21st Century Tumbleweed.
Tristan Rhodes wrote:
What would you have to do to handle commands which have parameters? Or would that be a symptom of bad design?
Have a class for arguments that is a parameter to the Execute method
ICommandExecutor::Execute( CommandArgs& args)
led mike