Skip to content

Commit

Permalink
20/10/29
Browse files Browse the repository at this point in the history
  • Loading branch information
WindRunnerMax committed Oct 29, 2020
1 parent c0853c3 commit 0522384
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 0 deletions.
5 changes: 5 additions & 0 deletions CATALOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Catalog

**2020-10-28**
> 第247题:[独一无二的出现次数](LeetCode/独一无二的出现次数.md)
<br>

**2020-10-27**
> 第246题:[valueOf与toString](JavaScript/valueOf与toString.md)
Expand Down
121 changes: 121 additions & 0 deletions Patterns/命令模式.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# 命令模式
命令模式`Command Pattern`是一种数据驱动的设计模式,其属于行为型模式,别名为动作`Action`模式或事务`Transaction`模式,命令模式将请求以命令的形式包裹在对象中,并传给调用对象,调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象对请求排队或者记录请求日志,以及支持可撤销的操作。

## 描述
在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来进行设计,使得请求发送者与请求接收者消除彼此之间的耦合,让对象之间的调用关系更加灵活。命令模式可以对发送者和接收者完全解耦,发送者与接收者之间没有直接引用关系,发送请求的对象只需要知道如何发送请求,而不必知道如何完成请求。命令模式也可以用于实现基于事务的系统,一旦执行命令,便会继续保留命令的历史记录,如果最终命令成功执行,那么一切都很好,否则只需遍历历史记录并继续对所有已执行的命令执行撤消即可。

### 优点
* 降低系统的耦合度。
* 新的命令可以很容易地加入到系统中。
* 可以比较容易地设计一个命令队列和宏命令(组合命令)。
* 可以方便地实现对请求的Undo和Redo。

### 缺点
* 使用命令模式可能会导致某些系统有过多的具体命令类。因为针对每一个命令都需要设计一个具体命令类,因此某些系统可能需要大量具体命令类,这将影响命令模式的使用。

### 适用环境
* 系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。
* 系统需要在不同的时间指定请求、将请求排队和执行请求。
* 系统需要支持命令的撤销`Undo`操作和恢复`Redo`操作。
* 系统需要将一组操作组合在一起,即支持宏命令

## 实现

```javascript
// 假设我们有一个电灯,我们使用遥控器对其进行控制

class Bulb {
turnOn() {
console.log("Bulb has been lit!");
}

turnOff() {
console.log("Darkness!");
}
}

class Command {
execute(){
throw new Error("Abstract method cannot be called");
}

redo(){
throw new Error("Abstract method cannot be called");
}

undo(){
throw new Error("Abstract method cannot be called");
}
}

class TurnOnCommand extends Command{
constructor(bulb) {
super();
this.bulb = bulb;
}

execute() {
this.bulb.turnOn();
}

undo() {
this.bulb.turnOff();
}

redo() {
this.execute();
}
}

class TurnOffCommand extends Command {
constructor(bulb) {
super();
this.bulb = bulb;
}

execute() {
this.bulb.turnOff();
}

undo() {
this.bulb.turnOn();
}

redo() {
this.execute();
}
}

class RemoteControl {
submit(command) {
command.execute();
}
}

(function(){
var bulb = new Bulb();

var turnOn = new TurnOnCommand(bulb);
var turnOff = new TurnOffCommand(bulb);

var remote = new RemoteControl();
remote.submit(turnOn); // Bulb has been lit!
remote.submit(turnOff); // Darkness!
})();
```


## 每日一题

```
https://github.com/WindrunnerMax/EveryDay
```

## 参考

```
https://www.runoob.com/design-pattern/command-pattern.html
https://github.com/sohamkamani/javascript-design-patterns-for-humans#-command
https://design-patterns.readthedocs.io/zh_CN/latest/behavioral_patterns/command.html
```

1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -263,3 +263,4 @@
* [反转字符串](LeetCode/反转字符串.md)
* [两两交换链表中的节点](LeetCode/两两交换链表中的节点.md)
* [长按键入](LeetCode/长按键入.md)
* [独一无二的出现次数](LeetCode/独一无二的出现次数.md)

0 comments on commit 0522384

Please sign in to comment.