I can't figure out why the Gang of Four book used C++ class templates for simple commands in the command pattern. I understand how they could be used, but the why escapes me. Maybe it's a C++ thing.
Last night I was able to use Dart callback functions as simple commands. The GoF suggested callbacks as an alternative for commands, so I assume that there is no way to do something similar in C++. What I do not understand is why they needed a class template to generate classes for simple commands. Why not a single, simple class instead of class templates?
In the command pattern, the command links actions with receivers, so a very simple command might look something like:
class SimpleCommand implements Command {
var receiver;
var action;
List args;
SimpleCommand(this.receiver, this.action, [this.args]);
void call() {
// Call the action on the receiver here...
}
}To make that work in Dart, I need to use mirrors so that I can reflect on an object and invoke arbitrary methods:import 'dart:mirrors';
// ...
class SimpleCommand implements Command {
var receiver;
Symbol action;
List args;
SimpleCommand(this.receiver, this.action, [this.args]);
void call() {
reflect(receiver).invoke(action, this.args);
}
}With that, I can create a simple command on the robot that I have been using as an example: // ...
var moveNorth = new MoveNorthCommand(robot),
// ...
beSad = new SimpleCommand(robot, #say, ['Boo hoo.']);I can then assign that command to an invoker (a button in this example) and tell the invoker to... invoke: // ...
var btnUp = new Button("Up", moveNorth);
// ...
var btnTease = new Button("Tease Robot", beSad);
btnUp.press();
btnTease.press();
// ...That results in a sad robot:[pressed] Up I am moving Direction.NORTH [pressed] Tease Robot Boo hoo.I have to think that something similar to that is possible in C++. If type safety is the concern driving class templates, then I can get a little closer in Dart with generics. If I make my
SimpleCommand class be for a specific type of receiver:class SimpleCommand<T> implements Command {
T receiver;
Symbol action;
List args=[];
SimpleCommand(this.receiver, this.action, [this.args]);
void call() {
reflect(receiver).invoke(action, this.args);
}
}Then I can be assure myself that the receiver has the correct type assigned:var
// ...
beSad = new SimpleCommand<Robot>(robot, #say, ['Boo hoo.']);It is not exactly class templates, but nothing else in the pattern makes use of the command being a specific type—just that the command implement a common interface. In other words, I think this, along with last night's callbacks, is more than sufficient to serve as a simple command implementation in the command pattern.I think that just about does it for the command pattern. I may review one more time tomorrow, or it may be time to throw a dart at another pattern for Design Patterns in Dart.
Play with the code in DartPad: https://dartpad.dartlang.org/26e623a65566e561af77.
Day #38
No comments:
Post a Comment