The command pattern provides a mechanism by which details of how to invoke a method can beencapsulated so that the method can be invoked later or by a different component.
client:
let calc = Calculator();
calc.add(10);
calc.multiply(4);
calc.subtract(2);
println("Calc 1 Total: \(calc.total)");
let macro = calc.getMacroCommand();
let calc2 = Calculator();
macro(calc2);
println("Calc 2 Total: \(calc2.total)");
import Foundation;
class Calculator {
private(set) var total = 0;
typealias CommandClosure = (Calculator -> Void);
private var history = [CommandClosure]();
private var queue = dispatch_queue_create("arrayQ",DISPATCH_QUEUE_SERIAL);
func add(amount:Int) {
addMacro(Calculator.add,amount: amount);
total += amount;
}
func subtract(amount:Int) {
addMacro(Calculator.subtract,amount: amount);
total -= amount;
}
func multiply(amount:Int) {
addMacro(Calculator.multiply,amount: amount);
total = total * amount;
}
func divide(amount:Int) {
addMacro(Calculator.divide,amount: amount);
total = total / amount;
}
private func addMacro(method:Calculator -> Int -> Void,amount:Int) {
dispatch_sync(self.queue,{() in
self.history.append({ calc in method(calc)(amount)});
});
}
func getMacroCommand() -> (Calculator -> Void) {
var commands = [CommandClosure]();
dispatch_sync(queue,{() in
commands = self.history
});
return { calc in
if (commands.count > 0) {
for index in 0 ..< commands.count {
commands[index](calc);
}
}
};
}
}
protocol Command {
func execute(receiver:Any);
}
class CommandWrapper : Command {
private let commands:[Command];
init(commands:[Command]) {
self.commands = commands;
}
func execute(receiver:Any) {
for command in commands {
command.execute(receiver);
}
}
}
class GenericCommand<T> : Command {
private var instructions: T -> Void;
init(instructions: T -> Void) {
self.instructions = instructions;
}
func execute(receiver:Any) {
if let safeReceiver = receiver as? T {
instructions(safeReceiver);
} else {
fatalError("Receiver is not expected type");
}
}
class func createCommand(instuctions: T -> Void) -> Command {
return GenericCommand(instructions: instuctions);
}
}