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