命令模式,用来对请求的发送者和请求的接收者进行解耦的一种设计模式,为什么叫命令模式呢?因为在应用该模式时,引入了一个命令对象。
命令模式有三个角色,请求发送者,命令对象,请求的接收者(处理者),谁来给请求发送者和接收者解耦呢,命令对象,所以我们一思考就知道命令模式应该是这样的:
请求发送者发送请求,为了增强扩展性,需要面向抽象编程,所以首先有一个抽象命令对象,当然,还要有具体命令对象来对应具体接收者,从而使不同命令得到不同处理。
举例说明(例子参照《C#设计模式 刘伟 胡志刚 阎朝坤》开关示例):隔壁老王帮隔壁邻居修开关,隔壁也是倒霉,风扇开关和电灯泡开关都坏了,隔壁老王上街买开关,要买两个,然而他不用特意买两个不同的开关,他只需买两个一模一样的开关就行,修的时候,使用不同电线连接不同电器,灯泡和风扇自然都能正常工作。
在上面例子中,开关(请求发送者,发送通电,断电请求),电线(命令对象)封装请求,灯泡或风扇(请求接收者处理者)处理请求。通过电线,很好的将请求发送者和接受者进行了解耦,这样好处很大,灯泡坏了只换灯泡,开关坏了只换开关即可。
命令模式UML类图:
LampCommand和Lamp是同生共死关系,所以是组合关系。
示例代码:
请求发送者:
/****
* 请求发送者(开关)
* @author wjw
*
*/
public class Sender {
private AbstractCommand ac;
public Sender(AbstractCommand ac){
this.ac = ac;
}
/***
* 开关开
*/
public void open(){
ac.open();
}
/***
* 开关关
*/
public void close(){
ac.close();
}
}
抽象命令类:
/*****
* 抽象命令类
* @author wjw
*
*/
public abstract class AbstractCommand {
public abstract void open();
public abstract void close();
}
电灯命令类:
/****
* 电灯命令对象,封装电灯(命令接收者)
* @author wjw
*
*/
public class LampCommand extends AbstractCommand{
private Lamp lamp;
public LampCommand(){
lamp = new Lamp();
}
@Override
public void open() {
// TODO Auto-generated method stub
lamp.openLamp();
}
@Override
public void close() {
// TODO Auto-generated method stub
lamp.closeLamp();
}
}
风扇命令类:
public class FanCommand extends AbstractCommand{
private Fan fan;
public FanCommand(){
fan = new Fan();
}
@Override
public void open() {
// TODO Auto-generated method stub
fan.openFan();
}
@Override
public void close() {
// TODO Auto-generated method stub
fan.closeFan();
}
}
电灯类:
/****
* 电灯(请求接收者)
* @author wjw
*
*/
public class Lamp {
public void openLamp(){
System.out.println("开灯!");
}
public void closeLamp(){
System.out.println("关灯!");
}
}
风扇类:
/****
* 风扇类(请求处理者)
* @author wjw
*
*/
public class Fan {
public void openFan(){
System.out.println("开风扇!");
}
public void closeFan(){
System.out.println("关风扇!");
}
}
Main类:
public class Main {
public static void main(String[] args) {
AbstractCommand lampCommand = new LampCommand();
AbstractCommand fanCommand = new FanCommand();
Sender lampSwitcher = new Sender(lampCommand);
Sender fanSwitcher = new Sender(fanCommand);
lampSwitcher.open();
lampSwitcher.close();
fanSwitcher.open();
fanSwitcher.close();
}
}
运行结果:
开灯!
关灯!
开风扇!
关风扇!
通过以上示例代码可以看出,我们开关和灯泡或者风扇没有耦合,相同的开关,既可以用在灯泡上,又可以用在风扇上,一个电灯泡,可以使用A型开关,也可以使用B型开关,其中的原理就是多了一个中间件,用来给他俩解耦,转发请求。
说明:命令模式就是将一个具体的请求封装成一个对象,将请求的发送者与接收者解耦。
我们为什么要用命令模式这个设计模式呢?设想这样一个场景,某厂家生产的电灯,开关和灯泡是连在一起的,灯泡10000元,开关10块,某天开关坏了,厂家说要把灯泡一起换了,你同意吗?正常人估计会把厂家踹一边,自己在家找个风扇不用的开关给电灯换上,继续使用。所以只要有正常人的思维理解命令模式不难。
如有错误,欢迎指正
end