I have a tree-like structure of objects. Objects have different types but all of them are inherited from the same base class. Now I want to send some kind of command objects to the nodes. Command object has address of the target node and should be passed through root node and intermediate nodes untill it reaches the target node. Target node accepts command and allows it to perform some actions on the node:
void Node::processCommand (Command& cmd) {
if(cmd.address == this->address)
cmd.execute(this);
else
child[cmd.address]->processCommand(cmd);
}
First question: is it a command pattern, or may be some of it's kind?
Next, consider I have nodes of classes ClassA and ClassB and I want to send some commands to objects of both classes, and some commands only for objects of ClassB, something like that:
class CommandForBoth {
void execute (BaseClass* obj) {
obj->doSomething();
}
}
class CommandForB {
void execute (ClassB* obj) {
obj->doSomethingSpecial();
}
}
Is it possible to implement that without casts and without multiple methods for passing commands of different types, like:
void Node::processCommand (CommandForBoth& cmd);
void Node::processCommand (CommandForClassA& cmd);
void Node::processCommand (CommandForClassB& cmd);
Best Answer
Is it a command pattern ?
The command pattern implies that:
Command
.Client
creates a concrete command and sets theReceiver
.Invoker
launches the command, which will carry out its actions for the already definedReceiver
.Your approach does not meet these expectations:
CommandForBoth
andCommandB
do not share the same interface (but maybe you just didn't mention it in your snippet).Client
defining it at creation, it's theInvoker
who defines the target at execution.Invoker
is your initialNode
. But your Invoker might not launch the command, but forward it to one of it's child.Or is it a visitor pattern ?
A visitor pattern is designed for executing operations on an
ObjectStructure
. The structure is responsible to activate the visitor for its relevant element. Each element is responsible to invoke the visitor for their relevant sub-elements.This looks very close to what you are doing:
Node
corresponds to theObjectStructure
,Node
corresponds to anElement
Node::ProcessCommand(Command)
corresponds toElement::accept(Visitor)
Command
corresponds toVisitor
Command::execute(Node)
corresponds toVisitor::visit(Node)
The only unusual thing is that in a visitor pattern, the successive chain of
accept()
is in general performed by the elements to call the visitor for all the children, whereas here, theaccept()
only looks at the addressing and executes the visitor if the addressing matches.Implementation without cast
The visitor pattern has a solution for your casting issue: each
Visitor
(so for you, eachCommand
) has an override ofvisit()
(so for you:execute()
) for each of the different subtypes ofElements
(i.e.Nodes
) that exist. In your case, all the overrides but one would implement nothing (or will throw an exception).This is a drawback of the visitor pattern, that you may not want. Alternatively, if the
Nodes
are polymorphic, you could easily deviate from the "pure" visitor pattern, and use only oneexecute(BaseClass*)
: