# 设计模式之----命令模式

一、背景

该模式出现是为了解决一些问题:解耦,以达到对修改封闭,对扩展开放的原则(开闭原则);命令组合实现功能。

二、定义

将一个请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化;对请求排队或记录请求日子,以及支持撤销的操作。

本例以录音机播放和暂停为例:

普通模式:按下键盘,调用录音机去播放或者暂停(需要写不同的分支,耦合度高,扩展时需要直接改动这部分逻辑)
命令模式:按下键盘时,将不同的操作封装为不同的命令对象,在命令对象中调用录音机去播放或者暂停,而键盘只需要去请求不同的操作命令对象执行即可,这样就使请求者(键盘)和执行者(录音机)实现了松耦合的结构。

三、命令模式中的角色

1. 客户端角色

创建一个具体命令,并制定其接收者。(例子中的用户)

2. 抽象命令角色

所有命令的抽象接口,抽象执行方法。

3. 具体命令角色

持有接受者角色的引用,实现抽象命令接口的执行方法,并调用接受者执行具体操作。(例子中的播放、暂停命令)

4. 请求者角色

持有命令角色,定义不同的请求方法,对应执行不同的命令。(例子中的键盘)

5. 接受者角色

负责接收和具体执行命令。(录音机)

四、简单代码实现

1. 创建接受者

/**
 * 录音机:接受者,执行具体的命令
 *
 * Created by rytong on 2017/10/25.
 */

public class AudioPlayer {

    private static final String TAG = AudioPlayer.class.getSimpleName();

    // 播放
    public void play(){
        Log.e(TAG,"正在播放...");
    }
    // 暂停
    public void pause(){
        Log.e(TAG,"已经暂停");
    }
}

2. 创建抽象命令接口

/**
 * 抽象命令接口
 *
 * Created by rytong on 2017/10/25.
 */

public interface CommadInterface {
    public void excute();
}

3. 创建具体的命令角色

/**
 * 具体播放命令,持有接收者角色
 *
 * Created by rytong on 2017/10/25.
 */

public class PlayCommand implements CommadInterface {

    private AudioPlayer audioPlayer;

    public PlayCommand(AudioPlayer audioPlayer) {
        this.audioPlayer = audioPlayer;
    }

    @Override
    public void excute() {
        audioPlayer.play();
    }
}

4. 创建请求者

/**
 * 录音机按键:请求者角色,持有具体命令
 *
 * Created by rytong on 2017/10/25.
 */

public class AudioKeyboard {
    private CommadInterface playCommand;
    private CommadInterface pauseCommand;

    public void setPlayCommand(CommadInterface playCommand) {
        this.playCommand = playCommand;
    }

    public void setPauseCommand(CommadInterface pauseCommand) {
        this.pauseCommand = pauseCommand;
    }
    //播放
    public void play(){
        playCommand.excute();
    }

    //暂停
    public void pause(){
        pauseCommand.excute();
    }
}

5. 客户端实现播放和暂停

//客户端
//创建一个接受者
AudioPlayer audioPlayer = new AudioPlayer();
//创建具体的命令,制定接受者
PauseCommand pauseCommand = new PauseCommand(audioPlayer);
PlayCommand playCommand = new PlayCommand(audioPlayer);
//创建请求者
AudioKeyboard audioKeyboard = new AudioKeyboard();
audioKeyboard.setPauseCommand(pauseCommand);
audioKeyboard.setPlayCommand(playCommand);

//请求者执行对应命令
audioKeyboard.play();
audioKeyboard.pause();

6. 具体执行结果

10-25 10:36:37.182 23772-23772/com.commandpattern E/AudioPlayer: 正在播放...  
10-25 10:36:37.182 23772-23772/com.commandpattern E/AudioPlayer: 已经暂停

五、应用场景

  • 当某些操作需要对行为进行记录,撤销等操作时可以采用;
  • 系统设计时需要这种松耦合结构时;
  • 系统需要不同命令组合实现功能时。

例子:线程的执行(省略了接收者,直接在具体命令中处理具体操作),简单代码 如下:

new Thread(new Runnable() {
        @Override
        public void run() {
            //dosomething
        }
    }).start();

六、优点

  1. 更松散的耦合:调用者不需要哦知道内部具体做了什么处理,只知道结果。
  2. 更动态的控制,可以把不同的命令组装起来,动态执行(比如总共有20个命令,不同组合可以实现不同的效果,这样会比较灵活)
  3. 扩展性好,只需要扩展新的命令,无需修改原有的逻辑。

七、缺点

如果系统比较庞大时,每个命令都需要编写一个新的类,这样系统会看起来非常臃肿;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值