Saturday, December 19, 2015

Generic Commands


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