0x1、定义
原始定义
将一个请求(命令)封装成一个对象,从而让我们可以使用 不同的请求参数化其他对象(依赖注入),且支持请求的排队执行、记录日志、撤销等功能(附加控制)。
落实到编码实现,命令模式用的最核心的实现手段就是:将函数封装成对象以便传递
,当你所用的编程语言不支持函数作为参数传递,就可以考虑用下它了。把函数封装成对象,还可以存储,控制执行,这也是命令模式的优点~
0x2、写个简单例子
用命令模式写个音乐播放控制的例子吧,先是业务实体:
public class Music { private String name; private String url; public Music(String name, String url) { this.name = name; this.url = url; } public String getName() { return name; } public String getUrl() { return url; } }
接着到 抽象命令类
→ 声明要做的操作:
public interface ICommand { void execute(); }
再接着到 抽象接收者
→ 声明要执行的命令,同时提供给客户端使用:
public interface IPlayer { void setPlayList(List<Music> musics); void play(); void play(int cursor); void next(); void pre(); void pause(); }
紧接着到 具体命令类
→ 实现抽象命令类,存储一个接收者,执行调用具体命令时,委托给接收者执行具体方法:
public class SetPlayListCommand implements ICommand { private final IPlayer player; private List<Music> musics; public SetPlayListCommand(IPlayer player) { this.player = player; } @Override public void execute() { player.setPlayList(musics); } public void setPlayList(List<Music> musics) { this.musics = musics; } } public class PlayCommand implements ICommand { private final IPlayer player; public PlayCommand(IPlayer player) { this.player = player; } @Override public void execute() { player.play(); } } public class NextCommand implements ICommand { private final IPlayer player; public NextCommand(IPlayer player) { this.player = player; } @Override public void execute() { player.next(); } } // 剩余两个命令类似,调用不同的player方法而已...
再接着到 具体接收者
→ 实现抽象接收者,接收命令并执行真实代码逻辑:
public class MusicPlayer implements IPlayer { private int cursor = -10000; // 当前播放游标 private int pauseCursor = -10000; // 当前暂停游标 private final List<Music> musics = new ArrayList<>(); @Override public void setPlayList(List<Music> musics) { this.musics.clear(); if(musics == null || musics.isEmpty()) { System.out.println("设置播放列表不能为空!"); } else { this.musics.addAll(musics); this.cursor = -10000; System.out.println("列表设置成功,当前曲目:"); for(Music music: this.musics) { System.out.println("【" + music.getName() +"】"); } } } @Override public void play() { if(musics.size() == 0) { System.out.println("当前播放列表为空,请先设置播放列表"); } else { if(cursor == -10000) { cursor = 0; System.out.println("开始播放:" + musics.get(0).getName()); } else { if(cursor < musics.size()) { if(cursor == pauseCursor) { System.out.println("继续播放:" + musics.get(cursor).getName()); pauseCursor = -10000; } else { if(cursor < 0) { cursor = musics.size() - 1; } System.out.println("开始播放:" + musics.get(cursor).getName()); } } else { System.out.println("播放列表歌曲已经播放完毕,重头开始播放"); cursor = 0; System.out.println("开始播放:" + musics.get(0).getName()); } } } } @Override public void next() { cursor++; play(); } @Override public void pre() { cursor--; play(); } @Override public void pause() { pauseCursor = cursor; System.out.println("暂停播放"); } }