zoukankan      html  css  js  c++  java
  • 行为型模式之Command模式

    命令模式将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,

    并且可以对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。

    概念描述

    把命令的调用者与执行者分开,使双方不必关心对方是如何操作的。
    比如有一组文件操作的命令:新建文件、复制文件、删除文件。如果把这三个操作都封装成一个命令类,客户端只需要知道有这三个命令类即可,至于命令类中封装好的逻辑,客户端则无需知道。

    在JDK中的体现

    允许子类重载部分父类而不需要完全重写。
    * java.util.Collections#sort()
    * java.io.InputStream#skip()
    * java.io.InputStream#read()
    * java.util.AbstractList#indexOf()


    参与角色

    Command类:是一个抽象类,类中对需要执行的命令进行声明,一般来说要对外公布一个execute方法用来执行命令。
    ConcreteCommand类:Command类的实现类,对抽象类中声明的方法进行实现。
    Client类:最终的客户端调用类。
    Invoker类:调用者,负责调用命令。
    Receiver类:接收者,负责接收命令并且执行命令。

    命令模式实例

    当我们调用时,执行的时序首先是调用者类,然后是命令类,最后是接收者类。
    一条命令的执行被分成了三步,耦合度要比把所有的操作都封装到一个类中要低的多。

    public abstract class Command {
    	
    	public abstract void execute();
    
    }
    
    /**
     * 具体命令的实现类
     * @author bingyue56@163.com 
     */
    public class ConcreteCommand extends Command{
    	
    	private Receiver receiver;
    	
    	public ConcreteCommand(Receiver receiver){
    		this.receiver=receiver;
    	}
    
    	/**
    	 * 具体的调用通过命令接收者来实现
    	 */
    	@Override
    	public void execute() {
    		this.receiver.action();
    	}
    }
    
    public class Receiver {
    
    	/**
    	 * 真正执行命令操作的代码
    	 */
    	public void action(){
    		System.out.println("命令接收者-执行具体业务逻辑");
    	}
    }
    

      

    /**
     * 调用者 负责调用命令
     */
    public class Invoker {
    
    	private Command command;  
    	
        public void setCommand(Command command) {  
            this.command = command;  
        }  
        public void action(){  
            this.command.execute();  
        }  
    }
    

      

    /**
     * 客户端调用
     * @author bingyue56@163.com 
     */
    public class Client {
    
    	public static void main(String[] args){
    		//得到业务逻辑执行者
    		Receiver receiver=new Receiver();
    		//命令类-注入具体业务逻辑接收者
    		Command command =new ConcreteCommand(receiver);
    		/**
    		 * 两种调用方式
    		 * 1.命令类直接调用执行
    		 */
    		command.execute();
    		/**
    		 * 2.通过invoker的方式注入命令
    		 */
    		Invoker invoker=new Invoker();
    		invoker.setCommand(command);
    		//调用内部command的执行
    		invoker.action();
    	}
    	
    }

    适用场景

    1.使用命令模式作为"CallBack"在面向对象系统中的替代。CallBack讲的便是先将一个函数登记上,然后在以后调用此函数。

    2.需要在不同的时间指定请求、将请求排队。一个命令对象和原先的请求发出者可以有不同的生命期。换言之,原先的请求发出者可能已经不在了,而命令对象本身仍然是活动的。这时命令的接收者可以是在本地,也可以在网络的另外一个地址。命令对象可以在序列化之后传送到另外一台机器上去。

    3.系统需要支持命令的撤消(undo)。命令对象可以把状态存储起来,等到客户端需要撤销命令所产生的效果时,可以调用undo()方法,把命令所产生的效果撤销掉。命令对象还可以提供redo()方法,以供客户端在需要时,再重新实施命令效果。

    4.如果一个系统要将系统中所有的数据更新到日志里,以便在系统崩溃时,可以根据日志里读回所有的数据更新命令,重新调用Execute()方法一条一条执行这些命令,从而恢复系统在崩溃前所做的数据更新。

    参考整理自:

    Java之命令模式(Command Pattern)

    23种设计模式(10):命令模式   

  • 相关阅读:
    【IdentityServer4文档】- 整体情况
    【IdentityServer4文档】- 欢迎来到 IdentityServer4 (ASP.NET Core 3.x)
    证券相关基础概念
    [基于NetCore的简单博客系统]-登录
    JAVA mysql数据库 配置
    简单验证码识别及登陆并下载页面
    Java 无法初始化Connection的问题
    MUI scroll 定位问题
    CentOS7 安装 MySql
    ASP.NET CORE 2.0 文档中文正式版已经出来了
  • 原文地址:https://www.cnblogs.com/binyue/p/4516498.html
Copyright © 2011-2022 走看看