Command模式
将函数封装成了一个类。以下例子中Command类只包含一个函数,但也可以包含若干个。
C++实现
1 #include<iostream> 2 using namespace std; 3 4 class Command { 5 public: 6 virtual void doit() { 7 cout << "command\n"; 8 } 9 }; 10 11 class TurnonCommand : public Command { 12 public: 13 virtual void doit() { 14 cout << "turn on\n"; 15 } 16 }; 17 18 class Sensor { 19 public: 20 Sensor(Command* c): command(c) {} 21 void sense() { 22 if (condition) 23 command->doit();//Sensor不需要知道这个command到底是什么 24 } 25 private: 26 bool condition = true; 27 Command* command; 28 }; 29 30 int main() { 31 TurnonCommand turnOn = TurnonCommand(); 32 Command* c = &turnOn;//如果需要把这个Sensor执行的command改成“打印”, 33 //只需要加一行 Print print = Print(); 34 //然后把这一行改成Command* c = &print; 35 //而不需要更改Sensor的代码 36 Sensor s(c); 37 s.sense(); 38 return 0; 39 }
Command模式的优点
使连接关系和系统的逻辑主体分离
这些连接关系可以放到一个简单的文本文件中,系统初始化时根据文件构建出对应的系统。由于连接关系是在程序以外确定的,因此对它的调整不会导致整个系统的重新编译。
符合OCP
比如,打印机的光学传感器检测到一张纸到达传送路径的某个特定的点后,需要启动某个离合器。为了实现这个功能,根据Command模式,我们只需要绑定一个启动命令到传感器上。如果某一天我们需要这个传感器不去启动离合器而是暂停一个发动机(我也不知道我们为什么要这么做),那么只需要把传感器绑定的命令改一下就可以了,传感器、离合器、发动机的代码都不需要改。如果代码是这个样子的:
1 class Sensor { 2 … 3 void sense() { 4 if (paper_arrived) 5 clutch_on(); 6 } 7 … 8 };
那么当我们需要更改这个传感器执行的命令时,必须更改这个class的代码,把clutch_on()改为pause(),这就违反了OCP。
解耦,提高复用性
仍然以打印机为例。当我们需要把这个传感器用到其他设备上时,不需要更改它本身的代码,只给它绑定新的命令就可以了。