美文网首页Java设计模式
Java实现23种设计模式(十二):命令模式

Java实现23种设计模式(十二):命令模式

作者: 依然慢节奏 | 来源:发表于2020-06-10 15:22 被阅读0次

    二十三种设计模式分类

    设计模式三大分类.jpg

    一、概述

    命令(Command)模式的定义如下:将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。这样两者之间通过命令对象进行沟通,这样方便将命令对象进行储存、传递、调用、增加与管理。
    主要解决:在软件系统中,行为请求者与行为实现者通常是一种紧耦合的关系,但某些场合,比如需要对行为进行记录、撤销或重做、事务等处理时,这种无法抵御变化的紧耦合的设计就不太合适。

    优点

    1. 降低系统的耦合度。命令模式能将调用操作的对象与实现该操作的对象解耦。
    2. 增加或删除命令非常方便。采用命令模式增加与删除命令不会影响其他类,它满足“开闭原则”,对扩展比较灵活。
    3. 可以实现宏命令。命令模式可以与组合模式
      结合,将多个命令装配成一个组合命令,即宏命令。
    4. 方便实现UndoRedo 操作。命令模式可以与后面介绍的备忘录模式
      结合,实现命令的撤销与恢复。

    缺点

    可能产生大量具体命令类。因为计对每一个具体操作都需要设计一个具体命令类,这将增加系统的复杂性。

    场景

    认为是命令的地方都可以使用命令模式,比如:
    1、GUI 中每一个按钮都是一条命令。
    2、模拟CMD


    二、实现

    1. 结构图

    命令模式包含以下主要角色。

    • 抽象命令类(Command)角色:声明执行命令的接口,拥有执行命令的抽象方法 execute()。
    • 具体命令角色(Concrete Command)角色:是抽象命令类的具体实现类,它拥有接收者对象,并通过调用接收者的功能来完成命令要执行的操作。
    • 实现者/接收者(Receiver)角色:执行命令功能的相关操作,是具体命令对象业务的真正实现者。
    • 调用者/请求者(Invoker)角色:是请求的发送者,它通常拥有很多的命令对象,并通过访问命令对象来执行相关请求,它不直接访问接收者。
    命令模式

    PS:UML结构图可以参考,例子实现并不根据UML图来完成,灵活实现即可;

    2. 实现

    • 文字内容实体类,命令针对内容操作
    package cn.missbe.model.command;
    
    /**
     * Copyright (c) 2020.
     * Email: love1208tt@foxmail.com
     * @author lyg  2020/4/29 下午10:03
     * description:
     **/
    
    public class Content {
    
        private String name;
    
        public Content(String name) {
            this.name = name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    
        @Override
        public String toString() {
            return "Content{" + "name='" + name + '\'' + '}';
        }
    }
    
    • 命令类集合
    package cn.missbe.model.command;
    
    /**
     * Copyright (c) 2020.
     * Email: love1208tt@foxmail.com
     *
     * @author lyg  2020/4/29 下午10:00
     * description:
     **/
    
    public abstract class Command {
    
        protected Content content;
    
        /**
         * 执行命令
         */
        public abstract void execute();
    
        /**
         * 撤销命令
         */
        public abstract void undo();
    }
    
    class InsertCommand extends Command {
        private String origin;
    
        public InsertCommand(Content content) {
            this.content = content;
        }
    
        @Override
        public void execute() {
            origin = this.content.getName();
            this.content.setName(this.content.getName() +  " [InsertCommand].");
        }
    
        @Override
        public void undo() {
            this.content.setName(origin);
        }
    }
    
    class CopyCommand extends Command {
    
        private String origin;
    
        public CopyCommand(Content content) {
            this.content = content;
        }
    
        @Override
        public void execute() {
            origin  = this.content.getName();
            this.content.setName(origin + origin);
        }
    
        @Override
        public void undo() {
            this.content.setName(origin);
        }
    }
    
    class DeleteCommand extends Command {
    
        private String origin;
    
        public DeleteCommand(Content content) {
            this.content = content;
        }
    
        @Override
        public void execute() {
            origin = content.getName();
            content.setName(origin.substring(0, origin.length() - 3));
        }
    
        @Override
        public void undo() {
            content.setName(origin);
        }
    }
    
    • 命令链式调用,实现执行和撤销功能
    package cn.missbe.model.command;
    
    import java.util.Deque;
    import java.util.LinkedList;
    
    /**
     * Copyright (c) 2020.
     * Email: love1208tt@foxmail.com
     * @author lyg  2020/4/29 下午10:19
     * description:
     * 命令链:责任链
     **/
    
    public class CommandChain {
        /**先进后出*/
        private Deque<Command> commands = new LinkedList<>();
    
        public CommandChain takeCommand(Command command) {
            /*执行命令*/
            command.execute();
            /*添加命令-撤销命令时使用*/
            commands.push(command);
    
            return this;
        }
    
        public CommandChain undoCommand(){
            /*执行的最后一个命令*/
            Command command = commands.pop();
            /*执行undo命令*/
            command.undo();
    
            return this;
        }
    }
    
    • 主类,实现调用
    package cn.missbe.model.command;
    
    /**
     * Copyright (c) 2020.
     * Email: love1208tt@foxmail.com
     * @author lyg  2020/4/29 下午9:54
     * description:
     * 命令模式:
     * 将一个请求封装成一个对象,从而使您可以用不同的请求对客户进行参数化
     * 在某些场合,比如要对行为进行"记录、撤销/重做、事务"等处理,这种无法抵御变化的紧耦合是不合适的。
     * 在这种情况下,如何将"行为请求者"与"行为实现者"解耦?将一组行为抽象为对象,可以实现二者之间的松耦合。
     **/
    
    public class Main {
        public static void main(String[] args) {
            /*
             * 这里使用责任链模式+命令模式实现撤销(undo)功能
             */
            Content content = new Content("【Origin Content】");
            InsertCommand insertCommand = new InsertCommand(content);
            CopyCommand copyCommand = new CopyCommand(content);
            DeleteCommand deleteCommand = new DeleteCommand(content);
    
            CommandChain commandChain  = new CommandChain();
            commandChain.takeCommand(insertCommand)
                    .takeCommand(copyCommand)
                    .takeCommand(copyCommand)
                    .undoCommand()
                    .takeCommand(deleteCommand);
            System.out.println(content);
        }
    }
    

    相关文章

      网友评论

        本文标题:Java实现23种设计模式(十二):命令模式

        本文链接:https://www.haomeiwen.com/subject/ydeutktx.html