使用命令模式重构播放器控制条

简介: 假如我们开发一个播放器,播放器有播放功能、拖动进度条功能、停止播放功能、暂停功能,我们在操作播放器的时候并不是直接调用播放器的方法,而是通过一个控制条去传达指令给播放器内核,具体传达什么指令,会被封装为一个个按钮。那么每个按钮就相当于对一条命令的封装。用控制条实现了用户发送指令与播放器内核接收指令的解耦。下面来看代码,首先创建播放器内核GPlayer类。

本文节选自《设计模式就该这样学》

1 命令模式的UML类图

命令模式的UML类图如下图所示。

2021112216513838.png

2 使用命令模式重构播放器控制条

假如我们开发一个播放器,播放器有播放功能、拖动进度条功能、停止播放功能、暂停功能,我们在操作播放器的时候并不是直接调用播放器的方法,而是通过一个控制条去传达指令给播放器内核,具体传达什么指令,会被封装为一个个按钮。那么每个按钮就相当于对一条命令的封装。用控制条实现了用户发送指令与播放器内核接收指令的解耦。下面来看代码,首先创建播放器内核GPlayer类。

public class GPlayer {
    public void play(){
        System.out.println("正常播放");
    }
    public void speed(){
        System.out.println("拖动进度条");
    }
    public void stop(){
        System.out.println("停止播放");
    }
    public void pause(){
        System.out.println("暂停播放");
    }
}

创建命令接口IAction类。

public interface IAction {
    void execute();
}

然后分别创建操作播放器可以接收的指令,播放指令PlayAction类的代码如下。

public class PlayAction implements IAction {
    private GPlayer gplayer;
    public PlayAction(GPlayer gplayer) {
        this.gplayer = gplayer;
    }
    public void execute() {
        gplayer.play();
    }
}

暂停指令PauseAction类的代码如下。

public class PauseAction implements IAction {
    private GPlayer gplayer;
    public PauseAction(GPlayer gplayer) {
        this.gplayer = gplayer;
    }
    public void execute() {
        gplayer.pause();
    }
}

拖动进度条指令SpeedAction类的代码如下。

public class SpeedAction implements IAction {
    private GPlayer gplayer;
    public SpeedAction(GPlayer gplayer) {
        this.gplayer = gplayer;
    }
    public void execute() {
        gplayer.speed();
    }
}

停止播放指令StopAction类的代码如下。

public class StopAction implements IAction {
    private GPlayer gplayer;
    public StopAction(GPlayer gplayer) {
        this.gplayer = gplayer;
    }
    public void execute() {
        gplayer.stop();
    }
}

最后创建控制条Controller类。

public class Controller {
    private List<IAction> actions = new ArrayList<IAction>();
    public void addAction(IAction action){
        actions.add(action);
    }
    public void execute(IAction action){
        action.execute();
    }
    public void executes(){
        for(IAction action : actions){
            action.execute();
        }
        actions.clear();
    }
}

从上面代码来看,控制条可以执行单条命令,也可以批量执行多条命令。下面来看客户端测试代码。

public static void main(String[] args) {
        GPlayer player = new GPlayer();
        Controller controller = new Controller();
        controller.execute(new PlayAction(player));
        controller.addAction(new PauseAction(player));
        controller.addAction(new PlayAction(player));
        controller.addAction(new StopAction(player));
        controller.addAction(new SpeedAction(player));
        controller.executes();
}

由于控制条已经与播放器内核解耦了,以后如果想扩展新命令,只需增加命令即可,控制条的结构无须改动。

3 命令模式在JDK源码中的应用

首先来看JDK中的Runnable接口,Runnable相当于命令的抽象,只要是实现了Runnable接口的类都被认为是一个线程。

public interface Runnable {
    public abstract void run();
}

实际上调用线程的start()方法之后,就有资格去抢CPU资源,而不需要编写获得CPU资源的逻辑。而线程抢到CPU资源后,就会执行run()方法中的内容,用Runnable接口把用户请求和CPU执行进行解耦。

4 命令模式在JUnit源码中的应用

再来看一个大家非常熟悉的junit.framework.Test接口。

package junit.framework;
public interface Test {
    public abstract int countTestCases();
    public abstract void run(TestResult result);
}

Test接口中有两个方法,第一个是countTestCases()方法,用来统计当前需要执行的测试用例总数。第二个是run()方法,用来执行具体的测试逻辑,其参数TestResult是用来返回测试结果的。实际上,我们在平时编写测试用例的时候,只需要实现Test接口就被认为是一个测试用例,那么在执行的时候就会被自动识别。通常做法都是继承TestCase类,不妨来看一下TestCase的源码。

public abstract class TestCase extends Assert implements Test {
        ...
        public void run(TestResult result) {
        result.run(this);
     }
     ...
}

实际上,TestCase类也实现了Test接口。我们继承TestCase类,相当于也实现了Test接口,自然就会被扫描成为一个测试用例。


【推荐】Tom弹架构:30个设计模式真实案例(附源码),挑战年薪60W不是梦


本文为“Tom弹架构”原创,转载请注明出处。技术在于分享,我分享我快乐!

如果本文对您有帮助,欢迎关注和点赞;如果您有任何建议也可留言评论或私信,您的支持是我坚持创作的动力。

相关文章
|
Windows
万能脚本录制器(支持鼠标/键盘的前台和后台,支持多种绑定模式)
本人现承接各种脚本/程序。包括:网页脚本(网页数据读取,post提交,自动下注等。)办公脚本(Word Excel Xls操作等)安卓模拟器脚本游戏脚本(自动喊话等简单功能,复杂暂不接)等其他脚本各种程序。
14920 0
万能脚本录制器(支持鼠标/键盘的前台和后台,支持多种绑定模式)
|
6月前
|
索引
HMI-58-【多媒体】重构底部菜单
今天的这个没有新的内容,就是计划重新构建下底部菜单,开始是在每个界面里面都做了底部菜单,开始我以为每个界面都不一样,和面我研究了一下发现,每个界面的底部菜单都是一样的呀,那我们就好所了,开始重构。把底部菜单移到他的父页面中。
|
8月前
|
物联网
如何实现按键的短按、长按检测?
如何实现按键的短按、长按检测?
|
9月前
|
设计模式 Java
控制操作:解析Java设计模式中的命令模式
在软件开发领域,设计模式是一组经过验证的最佳实践方法,用于解决各种常见问题。命令模式是一种行为型设计模式,其目标是将请求封装成对象,使得可以参数化客户端传递不同的请求,从而实现操作的解耦。在本文中,我们将深入了解命令模式的核心思想、应用场景以及它在Java中的实际运用。
63 0
|
11月前
一个案例带你了解独立式键盘设计原理
一个案例带你了解独立式键盘设计原理
125 0
|
开发者 索引
如何实现水平关卡翻页功能
最近有几位同学问水平方向上的关卡翻页功能怎么做,这篇教程就详细的介绍一下水平的关卡翻页功能的实现方法。 如果游戏中的关卡数量比较多,一般有两种方式展示大量的关卡按钮,一种是垂直的滑动显示,这个比较简单,只需要使用一个“滚动列表”插件即可实现。另一种是水平方向的翻页显示,当然水平方向上也是可以滑动的,但是似乎很少看见有在水平方向上使用滑动的方式显示大量关卡按钮的(或许这样与我们的操作习惯不符,或许你可以尝试一下这种很少有人用的方式?),大部分水平方向关卡的切换都是使用点击按钮翻一页的方式。
85 0
|
设计模式
03.如何实现一个遥控器-命令模式
03.如何实现一个遥控器-命令模式
149 0
03.如何实现一个遥控器-命令模式
复用功能按键输入(一键多用)
复用功能按键输入(一键多用) 宏定义 按键初始化 延迟函数 按键处理 复位 主函数
200 0
|
API 开发者 容器
面向键盘操作的半自动化解决方案
面向键盘操作的半自动化解决方案
面向键盘操作的半自动化解决方案
|
前端开发
小视频源码,可控的跑马灯,无需焦点
小视频源码,可控的跑马灯,无需焦点
262 0

热门文章

最新文章