将这些命令封装成在一个类中,然后用户(调用者)再对这个类进行操作,这就是Command模式,换句话说,本来用户(调用者)是直接调用这些命令的,如菜单上打开文档(调用者),就直接指向打开文档的代码,使用Command模式,就是在这两者之间增加一个中间者,将这种直接关系拗断,同时两者之间都隔离,基本没有关系了.(解耦)
本人水平一般 写的都是以后用来复习的知识点 没有观看的价值
命令模式 有五个部分 客户端 请求者 具体命令类 抽象方法类 接受者
先说下 录音机---典型的应用命令模式 比如录音机有4个键,名字为play,rewind,stop 那我们编程模拟实现功能的时候,可以就这样设计
class keypad{
void play(){
}
void rewind(){
}
void stop(){
}
}
keypad a;
a.play();
a.rewind();
a.stop();
这样就OK了 但是发起的命令和命令的执行者耦合了(还有的人说是当命令请求者必须知道接收者的实现细节也是耦合) 比如play 发起命令和执行命令都是在这个函数里面。 比如现在我要改变play的功能,那还要改变代码所以有了这个设计模式
class keypad{
private command playcommad,rewind,stop;
public void setplay(command p){
playcommand=p;
}
.......
public void play(){
playcommand.play();
}
}
实现这样的设计模式肯定需要一个接口类,这个接口类里面只用定义一个功能就行,public interface command{ pubic void execute(); }之后就是要具体的命令类比如public playcommand implements command{ void excute(){} } 可以在这个函数里面具体实现功能,但是其实这样也没有怎么解耦,比如你要是以前是从一个收音机的一个功能块实现的play功能现在要从另一个功能块呢 所以 最好这样设计 public playcommand implents command{ Receive receiive=null public command(receive r):receive=r{} public void execute(){ receive.play()} 而Receive 就是具体的接收者类 也就是实现具体功能的 以后可以参考这篇文章https://www.cnblogs.com/java-my-life/archive/2012/06/01/2526972.html
修改一下 这里用到的具体命令类 可以简化下不需要 在使用类似于虚函数这种东西了 可以用boost::function 前提是接收者的功能函数具有相似的结构 假设我们这里的play rewind stop 都具有相同的函数签名 void (void ) 那可以这样创建一个类
class command{
boost::function<void()>f_;
public:
command(boost::funciton<void()>f):f_(f){}
void excute(){
f_():
}
}
在请求者中 是这样的
class keypad{
command play(boost::function<void()>f):f_(f){}
void play(){
play.excute();
}
void rewind(){
rewind.excute();
}
void stop(){
}
}
更新 最新的理解 感觉之前的理解有点不深刻 首先关于解耦这个理解,,举个例子,比如拿vs 生成菜单栏里面的编译选项举例,我们就是调用者,点击编译后,直接调用了编译命令函数,那这就是耦合,耦合的缺点是,比如你还是想通过编译这个选项去编译,但是现在的编译和之前的编译不一样,那你只能修改编译函数的代码。但是如果在调用者(我)和实现者(菜单中实现编译选项的函数)之间有中间者,那么就是解耦了 命令模式是对命令的封装,也就是将具体命令单独拿出来作为一个类,将它实现的细节封装起来, 中间者来将调用者和实现者进行联系 具体实现就是定义个抽象命令类接口,具体命令类(play,stop)继承实现它, 在Invoker类中,进行相应的指定,这样执行的时候可以根据我们自己去选择不同的具体实现方法 当然还有一个很大的好处,因为现在类是一个方法(这个方法是调用接收者的方法的也就是接收者里面的方法才是具体的方法,这样可以从不同的地方进行控制,比如gui,cmd等等),那就可以将我们执行的步骤记录,必要时根据记录撤销或者重复执行。
现在可以用funciton+bind来简化相同类型的签名 具体做法是 接收者还是要有的 但是具体的方法不在是用虚函数的方法(抽象基类+继承的基类),而可以用function+bind
可以创建一个command里面封装了一个funtion function的类型是接收类中一类函数签名的类型 这样在创建一个这样的类的时候可以将接收者中的类方法和函数对象进行绑定生成function类