요구사항을 객체로 캡슐화할 수 있으며,매개변수를 사용하여 여러 가지 다른 요구 사항을 집어넣을 수 있다.
요청 내역을 큐에 저장하거나 로그로 기록할 수 있고, 작업취소 기능도 지원한다.
Client : ConcreteCommand를 생성하고 Reciver를 설정한다.
Invoker : 명령이 들어있고, exceute() 메서드를 호출함으로써 커맨드 객체에게 특정한 작업을 수행해 달라고 한다.
Command :
모든 커맨드 객체에서 구현해야 하는 인터페이스이다.
실행될 기능을 execute 메서드로 선언함
Reciver :
요구 사항을 수행하기 위해서 어떤 일을 처리해야 하는지 알고 있는 객체.
ConcreteCommand에서 execute 메서드를 구현할 때 필요한 클래스
즉, ConcreteCommand의 기능을 실행하기 위해 사용하는 수신자 클래스
ConcreteCommand : 특정 행동과 리시버 사이를 연결해준다.
execute() : 메서드에는 리시버에 있는 메서드를 호출하여 요청된 작업을 수행한다.
//Interface
abstract class ICommand {
abstract execute(args): void;
}
//Receiver
class State {
private _state: number;
constructor(state) {
this._state = state;
}
getState() {
return this._state;
}
setState() {
this._state = value;
}
}
//Invorker
class BankManager () {
private _state;
private _commands = {};
constructor() {
this._state = state;
}
registerCommands(...args) {
for (const cmd of args) {
this._commands[cmd.constructor.name] = cmd;
}
}
executeCmd(cmdName, param) {
this._commands[cmdName].execute(this._state,param)
}
}
//Command
class Deposit implements ICommand {
execute(...params):void {
const [state, amount] = params;
const prevState = state.getState()
state.setState(prevState + amount)
}
}
class Withdrawal implements ICommand {
execute(...params):void {
const [state, amount] = params;
const prevState = state.getState()
state.setState(prevState - amount)
}
}
//1.command 생성
const deposit = new Deposit();
const withdrawal = new Withdrawal();
//2.receiver 생성
const state = new State(0);
//3.invoker 인스턴스 & receiver 등록
const bankManager = new BankManager();
//4.command 등록
bankManager.registerCommands(deposit,withdrawal)
//5.command 지시
bankManager.executeCmd('Deposit',100)
bankManager.executeCmd('Deposit',1100)
console.log(state.getState()); // 1100
bankManager.executeCmd('withdrawal',1000)
console.log(state.getState()); // 100
class Command {
execute() {}
}
class PrintCommand extends Command {
constructor(printStr) {
this.printStr = printStr;
}
execute() {
console.log(`from print command : ${this.printStr}`)
}
}
const firstPrint = new PrintCommand('1')
const secondPrint = new PrintCommand('2')
firstPrint.execute() // from print command : 1
secondPrint.execute() // from print command : 2
class Dog {
sit() {
console.log('the dog sat down')
}
stay() {
console.log('the dog is staying')
}
}
class DogCommand extends Command {
constructor (dog,commands) {
this.dog = dog;
this.commands = commands;
}
execute() {
for (const command in this.commands) {
if (command == 'sit ') this.dog.sit()
if (command == 'stay ') this.dog.stay()
}
}
}
const baduk = new Dog();
const dogCommand = new DogCommand(baduk,['sit','stay','sit'])
dogCommand.execute()
// 'the dog sat down'
// 'the dog is staying'
// 'the dog sat down'
class Invoker {
constructor() {
this.commandList = [];
}
addCommand(command) {
this.commandList.push(command)
}
runCommand() {
for (const command in this.commandList) {
command.execute();
}
}
}
const invoker = Invoker();
invoker.addCommand(firstPrint)
invoker.addCommand(secondPrint)
invoker.addCommand(dogCommand)
invoker.runCommand();
// from print command : 1
// from print command : 2
// 'the dog sat down'
// 'the dog is staying'
// 'the dog sat down'
class Calculator {
constructor() {
this.value = 0;
this.history = [];
}
executeCommand(command) {
this.value = command.execute(this.value)
this.history.push(command)
}
undo() {
const command = this.history.pop()
this.value = command.undo(this.value)
}
}
class AddCommand {
constructor(valueToAdd) {
this.valueToAdd = valueToAdd
}
execute(currentValue) {
return currentValue + this.valueToAdd
}
undo(currentValue) {
return currentValue - this.valueToAdd
}
}
class MultiplyCommand {
constructor(valueToMultiply) {
this.valueToMultiply = valueToMultiply
}
execute(currentValue) {
return valueToMultiply * this.valueToMultiply
}
undo(currentValue) {
return valueToMultiply / this.valueToMultiply
}
}
const calculator = new Calculator();
calculator.executeCommand(new AddCommand(10))
calculator.executeCommand(new MultiplyCommand(2))
console.log(calculator.value) // 20
calculator.undo()
console.log(calculator.value) // 10
class AddThenMultiplyCommand {
constructor(valueToAdd,valueToMultiply) {
this.addCommand = new AddCommand(valueToAdd)
this.multiplyCommand = new MultiplyCommand(valueToMultiply)
}
execute(currentValue) {
const newValue = this.addCommand.excute(currentValue)
retrun this.multiplyCommand.execute(newValue)
}
undo(currentValue) {
const newValue = this.multiplyCommand.undo(currentValue)
retrun this.addCommand.undo(newValue)
}
}
calculator.executeCommand(new AddThenMultiplyCommand(10,2))
console.log(calculator.value) // 20
calculator.undo()
console.log(calculator.value) // 0