• 设计模式学习笔记之命令模式


    命令模式
        将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。
        说明:
        1、命令模式将发出请求的对象和执行请求的对象解耦;
        2、在被解耦的两者之间是通过命令对象进行沟通的。命令对象封装了接受者和一个或一组动作;
        3、调用者通过调用命令对象的execute()发出请求,这会使得接受者的动作被调用;
        4、调用者可以接受命令当做参数,甚至在运行时动态地进行;
        5、命令可以支持撤销,做法事实现一个undo()方法来回到exexcute()被执行前的状态;
        6、命令模式也可以用来实现日志和事物系统;
     
        优点:
        1、降低对象之间的耦合度;
        2、新的命令可以很容易地加入到系统中;
        3、可以比较容易地设计一个组合命令;
        4、调用同一方法实现不同的功能。
     
        缺点:
        使用命令模式可能会导致某些系统有过多的具体命令类。因为针对每一个命令都需要设计一个具体命令类,因此某些系统可能需要大量具体命令类,这将影响命令模式的使用。
     
        场景:
        1、系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互;
        2、系统需要在不同的时间指定请求、将请求排队和执行请求;
        3、系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作;
        4、系统需要将一组操作组合在一起,即支持宏命令;
     
        例子:
        录音机有播音(Play)、倒带(Rewind)和停止(Stop)功能,录音机的键盘便是请求者(Invoker)角色;Leslie是客户端角色,而录音机便是接收者角色。Command类扮演抽象命令角色,而PlayCommand、StopCommand和RewindCommand便是具体命令类。Leslie不需要知道播音(play)、倒带(rewind)和停止(stop)功能是怎么具体执行的,这些命令执行的细节全都由键盘(Keypad)具体实施。Leslie只需要在键盘上按下相应的键便可以了。
    /**
     * 命令接口。
     * 所有的命令对象需要实现该接口。
     * */
    public interface Commond {
     
        public void execute();
     
    }
    /**
     * 录音机--命令接受者
     * */
    public class AudioPlayer {
     
        public void play() {
            System.out.println("播放......");
        }
     
        public void stop() {
            System.out.println("暂停......");
        }
     
        public void rewind() {
            System.out.println("倒带......");
        }
    }
     
    /**
     * 录音机播放命令
     * 具体命令角色类
     * */
    public class PlayCommond implements Commond{
     
        AudioPlayer player;
     
        public PlayCommond(AudioPlayer player) {
            this.player = player;
        }
     
        // 调用接收对象(录音机)的 play() 方法
        public void execute() {
            player.play();
        }
     
    }
    /**
     * 录音机倒带命令
     * 具体命令角色类
     * */
    public class RewindCommond implements Commond{
     
        AudioPlayer player;
     
        public RewindCommond(AudioPlayer player) {
            this.player = player;
        }
     
        // 调用接收对象(录音机)的 rewind() 方法
        public void execute() {
            player.rewind();
        }
     
    }
    /**
     * 录音机暂停命令
     * 具体命令角色类
     * */
    public class StopCommond implements Commond{
     
        AudioPlayer player;
     
        public StopCommond(AudioPlayer player) {
            this.player = player;
        }
     
        // 调用接收对象(录音机)的 stop() 方法
        public void execute() {
            player.stop();
        }
     
    }
    /**
     * 键盘类
     * 请求者角色
     * */
    public class Keypad {
     
        private Commond play;
        private Commond stop;
        private Commond rewind;
     
        public void setPlayCommond(Commond play) {
            this.play = play;
        }
     
        public void setStopCommond(Commond stop) {
            this.stop = stop;
        }
     
        public void setRewindCommond(Commond rewind) {
            this.rewind = rewind;
        }
     
        // 执行播放方法
        public void play() {
            play.execute();
        }
     
        // 执行暂停方法
        public void stop() {
            stop.execute();
        }
     
        // 执行倒带方法
        public void rewind() {
            rewind.execute();
        }
    }
    /**
     * 具体人--莱斯利
     * 客户端角色
     * */
    public class Leslie {
     
        public static void main(String[] args) {
     
            // 创建接受者对象,即收音机对象
            AudioPlayer player = new AudioPlayer();
            // 创建命令者对象
            Commond play = new PlayCommond(player);
            Commond stop = new StopCommond(player);
            Commond rewind = new RewindCommond(player);
            // 创建请求者对象,即键盘对象
            Keypad keypad = new Keypad();
            keypad.setPlayCommond(play);
            keypad.setStopCommond(stop);
            keypad.setRewindCommond(rewind);
     
            // 播放
            keypad.play();
            // 暂停
            keypad.stop();
            // 倒带
            keypad.rewind();
        }
    }
        宏命令
        所谓宏命令简单点说就是包含多个命令的命令,是一个命令的组合。
        设想Leslie 的录音机有一个记录功能,可以把一个一个的命令记录下来,再在任何需要的时候重新把这些记录下来的命令一次性执行,这就是所谓的宏命令集功能。因此,Leslie 的录音机系统现在有四个键,分别为播音、倒带、停止和宏命令功能。此时系统的设计与前面的设计相比有所增强,主要体现在Julia类现在有了一个新方法,用以操作宏命令键。
    /**
     * 定义宏命令接口
     * */
    public interface MacroCommand extends Command{
     
        /**
         * 宏命令存储的管理方法
         * 可以添加一个成员命令
         */
        public void add(Command cmd);
     
        /**
         * 宏命令存储的管理方法
         * 可以删除一个成员命令
         */
        public void remove(Command cmd);
     
    }
    /**
     * 具体的宏命令,对存储的若干命令进行操作
     * */
    public class MacroAudioCommand implements MacroCommand{
     
        // 宏命令集合
        private List<Command> cmdList = new ArrayList<Command>();
     
        // 一次性执行宏命令集合中的各命令
        public void execute() {
            System.out.println("-------自动回放保存的命令-------");
            for(Command cmd : cmdList)  {
                cmd.execute();
            }
            System.out.println("------------回放完毕------------");
        }
     
        public void add(Command cmd) {
            cmdList.add(cmd);
        }
     
        public void remove(Command cmd) {
            cmdList.remove(cmd);
        }
     
    }
    /**
     * 具体人--莱斯利
     * 客户端角色
     * */
    public class Leslie {
     
        public static void main(String[] args) {
     
            // 创建接受者对象,即收音机对象
            AudioPlayer player = new AudioPlayer();
            // 创建命令者对象
            Command play = new PlayCommond(player);
            Command stop = new StopCommond(player);
            Command rewind = new RewindCommond(player);
     
            MacroCommand macro = new MacroAudioCommand();
            macro.add(play);
            macro.add(rewind);
            macro.add(stop);
            macro.execute();
        }
    }
    参考资料:《Head First 设计模式》
  • 相关阅读:
    WebEssentials 在vs2013 update5安装报错的解决方法.
    提高代码质量系列之三:我是怎么设计函数的?
    ValueInjecter----最好用的OOM(以微信消息转对象举例)
    我的第一个python程序--给2.x的print代码加上括号
    提高代码质量系列之二:重构小技巧——if篇
    提高代码质量系列之一:尽可能少写注释.
    Two-machine debugging
    12306个人敏感信息泄露
    纯手工秒杀VM,SE等虚拟机Handle
    2014版QQ个性显IP(源码+Bin)
  • 原文地址:https://www.cnblogs.com/LeslieXia/p/5494889.html
Copyright © 2020-2023  润新知