ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2021-11-22 17:03:36  阅读:165  来源: 互联网

标签:播放器 重构 execute gplayer void GPlayer 模式 public


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

1 命令模式的UML类图

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

file

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弹架构 』回复“设计模式”可获取完整源码。

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

本文为“Tom弹架构”原创,转载请注明出处。技术在于分享,我分享我快乐!
如果本文对您有帮助,欢迎关注和点赞;如果您有任何建议也可留言评论或私信,您的支持是我坚持创作的动力。关注微信公众号『 Tom弹架构 』可获取更多技术干货!

标签:播放器,重构,execute,gplayer,void,GPlayer,模式,public
来源: https://www.cnblogs.com/gupaoedu-tom/p/15589236.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有