zoukankan      html  css  js  c++  java
  • 北风设计模式课程---29、命令模式

    北风设计模式课程---29、命令模式

    一、总结

    一句话总结:

    整体系统如何初始做好设计,会非常节约时间,而无需管事大型项目还是小型项目,无需管事面向过程还是面向对象
    命令模式就是封装了类的调用:一个类的命令列表里面存各种类,然后遍历调用这些类的方法

    1、如果中小型项目的结构通过MVC本身就比较清晰了,还有必要过度使用设计模式么?

    没必要:设计模式虽然让代码更加工整了,但是也增加了很多类和很多代码,不一定划得来
    面向过程转面向对象也很容易。重构一下代码就好。然后可以按照需求增加这些设计模式。
    整体系统如何初始做好设计,会非常节约时间,而无需管事大型项目还是小型项目,无需管事面向过程还是面向对象

    2、面向对象编程和面向过程编程?

    照我看来,黑猫白猫,能抓到老鼠的就是好猫。面向过程配上mvc在中小型项目中也是够用的。
    面向过程转面向对象也很容易。重构一下代码就好。然后可以按照需求增加这些设计模式。
    整体系统如何初始做好设计,会非常节约时间,而无需管事大型项目还是小型项目,无需管事面向过程还是面向对象
    初始建议面向对象编程,结构清晰,不易出错,反而会节约时间的

    3、什么是命令模式?

    Command模式通过被称为Command的类封装了对目标对象的调用行为以及调用参数。


       Command模式也叫命令模式 ,是行为设计模
    式的一种。Command模式通过被称为
    Command的类封装了对目标对象的调用行为以
    及调用参数。

    4、在面向对象的程序设计中,一个对象调用另一个对象,一般情况下的调用过程是怎样的?

    1、创建目标对象实例;设置调用参数;调用目标对象的方法。
    2、命令模式:但在有些情况下有必要使用一个专门的类对这种调用过程加以封装,我们把这种专门的类称作command类。

    5、命令模式的应用场景?

    - 整个调用过程比较繁杂,或者存在多处这种调用。这时,使用Command类对该调用加以封装,便于功能的再利用。
    - 调用前后需要对调用参数进行某些处理。
    - 调用前后需要进行某些额外处理,比如日志,缓存,记录历史操作等。

    6、命令模式 实例?

    有卖苹果命令类,有卖香蕉命令类。小商贩Peddler类封装了卖苹果和卖香蕉命令。有服务员Waiter类,里面有命令列表数据结构,有添加命令和删除命令方法,也有sail方法就是一次调用苹果或香蕉命令类的sail方法。

    7、命令模式的角色和职责?

    1、Command:Command抽象类。Command.java
    2、ConcreteCommand:Command的具体实现类。AppleCommand.java;BananaCommand.java
    3、Receiver:需要被调用的目标对象。Peddler.java
    4、Invorker:通过Invorker执行Command对象。Waiter.java

    二、内容在总结中

    1、相关知识

    有卖苹果命令类,有卖香蕉命令类。小商贩Peddler类封装了卖苹果和卖香蕉命令。有服务员Waiter类,里面有命令列表数据结构,有添加命令和删除命令方法,也有sail方法就是一次调用苹果或香蕉命令类的sail方法。
     
    Command:Command抽象类。Command.java
    ConcreteCommand:Command的具体实现类。AppleCommand.java;BananaCommand.java
    Receiver:需要被调用的目标对象。Peddler.java
    Invorker:通过Invorker执行Command对象。Waiter.java

    2、代码

    Command:Command抽象类。Command.java

    package com.ibeifemg.ex4;
    
    public abstract class Command {
        private Peddler peddler;
        
        
        public Command(Peddler peddler) {
            this.peddler = peddler;
        }
        
        public Peddler getPeddler() {
            return peddler;
        }
    
        public void setPeddler(Peddler peddler) {
            this.peddler = peddler;
        }
    
        public abstract void sail();
    }

    ConcreteCommand:Command的具体实现类。

    AppleCommand.java;

    package com.ibeifemg.ex4;
    
    public class AppleCommand extends Command {
    
        public AppleCommand(Peddler peddler) {
            super(peddler);
        }
    
        public void sail() {
            this.getPeddler().sailApple();
        }
        
    }

    BananaCommand.java

    package com.ibeifemg.ex4;
    
    public class BananaCommand extends Command{
    
        public BananaCommand(Peddler peddler) {
            super(peddler);
        }
    
        public void sail() {
            this.getPeddler().sailBanana();
        }
    
    }

    Receiver:需要被调用的目标对象。Peddler.java

    package com.ibeifemg.ex4;
    
    /*
     * 小商贩
     */
    public class Peddler {
        
        //卖苹果
        public void sailApple() {
            System.out.println("卖苹果");
        }
        
        //卖香蕉
        public void sailBanana() {
            System.out.println("卖香蕉");
        }
        
    }

    Invorker:通过Invorker执行Command对象。Waiter.java

    package com.ibeifemg.ex4;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class Waiter {
        private List<Command> commands = new ArrayList<Command>();
    
    
        public void setOrder(Command command) {
            commands.add(command);
        }
    
        public void removeOrder(Command command) {
            commands.remove(command);
        }
        
        public void sail() {
            for(Command command : commands) {
                command.sail();
            }
        }
    }

    客户端调用:

    package com.ibeifemg.ex4;
    
    public class MainClass {
        public static void main(String[] args) {
            Peddler peddler = new Peddler();
    //        peddler.sailApple();
    //        peddler.sailBanana();
            
            Command appleCommand = new AppleCommand(peddler);
            Command bananaCommand = new BananaCommand(peddler);
    //        appleCommand.sail();
    //        bananaCommand.sail();
            Waiter waiter = new Waiter();
            
            //下订单
            waiter.setOrder(appleCommand);
            waiter.setOrder(bananaCommand);
            
            //移除订单某项
            waiter.removeOrder(appleCommand);
            
            waiter.sail();
        }
    }

    三、java设计模式-----23、命令模式

    转自或参考:java设计模式-----23、命令模式
    https://www.cnblogs.com/xiaobai1226/p/8651632.html

      概念:

      Command模式也叫命令模式 ,是行为设计模式的一种。Command模式通过被称为Command的类封装了对目标对象的调用行为以及调用参数。

      命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。

      主要解决:

      在软件系统中,“行为请求者”与“行为实现者”通常呈现一种“紧耦合”。但在某些场合,比如要对行为进行“记录、撤销/重做、事务”等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将“行为请求者”与“行为实现者”解耦?将一组行为抽象为对象,实现二

    者之间的松耦合。这就是命令模式(Command Pattern)。

      下面,举一个小例子,但不是使用命令模式实现的

      新建一个Peddler类,是一个卖水果的小商贩

     1 /*
     2  * 小商贩
     3  */
     4 public class Peddler {
     5     /*
     6      * 卖苹果
     7      */
     8     public void sailApple(){
     9         System.out.println("卖苹果");
    10     }
    11     
    12     /*
    13      * 卖香蕉
    14      */
    15     public void sailBanana(){
    16         System.out.println("卖香蕉");
    17     }
    18 }

      再建一个客户端

    1 public class MainClass {
    2     public static void main(String[] args) {
    3         Peddler peddler = new Peddler();
    4         peddler.sailApple();
    5         peddler.sailBanana();
    6     }
    7 }

      结果:

      命令模式的应用场景

      在面向对象的程序设计中,一个对象调用另一个对象,一般情况下的调用过程是:创建目标对象实例;设置调用参数;调用目标对象的方法(像刚才的例子MainClass中,创建Peddler实例,再调度其中的方法)。

      但在有些情况下有必要使用一个专门的类对这种调用过程加以封装,我们把这种专门的类称作command类。

      1、整个调用过程比较繁杂,或者存在多处这种调用。这时,使用Command类对该调用加以封装,便于功能的再利用。

      2、调用前后需要对调用参数进行某些处理。

      3、调用前后需要进行某些额外处理,比如日志,缓存,记录历史操作等。

      命令模式的结构

      

      命令模式的角色和职责

      1、Command:Command抽象类,定义命令的接口,声明执行的方法。。

      2、ConcreteCommand:Command的具体实现类,命令接口实现对象,是“虚”的实现;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。

      3、Receiver:需要被调用的目标对象,接收者,真正执行命令的对象。任何类都可能成为一个接收者,只要它能够实现命令要求实现的相应功能。

      4、Invorker:通过Invorker执行Command对象,要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口。

      5、Client:创建具体的命令对象,并且设置命令对象的接收者。注意这个不是我们常规意义上的客户端,而是在组装命令对象和接收者,或许,把这个Client称为装配者会更好理解,因为真正使用命令的客户端是从Invoker来触发执行。

     

      当然,我们的例子非常简单,用不到命令模式,我们假设操作很复杂,用命令模式改造一下

      首先,创建类对调用过程进行一个封装,先创建一个Command抽象父类

     1 public abstract class Command {
     2     //包含一个Receiver的引用
     3     private Peddler peddler;
     4     
     5     public Command(Peddler peddler) {
     6         super();
     7         this.peddler = peddler;
     8     }
     9 
    10     public Peddler getPeddler() {
    11         return peddler;
    12     }
    13 
    14     public void setPeddler(Peddler peddler) {
    15         this.peddler = peddler;
    16     }
    17 
    18     public abstract void sail();
    19 }

      接下来创建ConcreteCommand,每一个操作都要创建一个,所以我们要创建两个Apple与Banana

     1 /*
     2  * Apple
     3  */
     4 public class AppleCommand extends Command{
     5 
     6     public AppleCommand(Peddler peddler) {
     7         super(peddler);
     8     }
     9 
    10     @Override
    11     public void sail() {
    12         //还可以在这句话前后做额外的处理
    13         this.getPeddler().sailApple();
    14     }
    15 
    16 }
     1 /*
     2  * Banana
     3  */
     4 public class BananaCommand extends Command{
     5 
     6     public BananaCommand(Peddler peddler) {
     7         super(peddler);
     8     }
     9 
    10     @Override
    11     public void sail() {
    12         //还可以在这句话前后做额外的处理
    13         this.getPeddler().sailBanana();
    14     }
    15 
    16 }

       最后,修改MainClass

     1 public class MainClass {
     2     public static void main(String[] args) {
     3         Peddler peddler = new Peddler();
     4         Command appleCommand = new AppleCommand(peddler);
     5         Command bananaCommand = new BananaCommand(peddler);
     6         
     7         appleCommand.sail();
     8         bananaCommand.sail();
     9         
    10     }
    11 }

       但是这样还不够好,可以看到这是直接由命令来调用sail方法的,这样不好,我们希望由专人来卖东西,就像人家请了一个服务员一样,所以我们再新建一个Invorker

    public class Waiter {
        private Command command;
    
        public Command getCommand() {
            return command;
        }
    
        public void setCommand(Command command) {
            this.command = command;
        }
        
        public void sail(){
            command.sail();
        }
    }

      再修改客户端

     1 public class MainClass {
     2     public static void main(String[] args) {
     3         Peddler peddler = new Peddler();
     4         Command appleCommand = new AppleCommand(peddler);
     5         Command bananaCommand = new BananaCommand(peddler);
     6         
     7         Waiter waiter = new Waiter();
     8         waiter.setCommand(appleCommand);
     9         waiter.sail();
    10         
    11         waiter.setCommand(bananaCommand);
    12         waiter.sail();
    13         
    14     }
    15 }

      这样Client就直接与Invorker进行通话

      我们现在只能添加命令,却不能移除命令,,而且一次只能有一个命令,我们继续改造

     1 public class Waiter {
     2     private Map<String,Command> commands;
     3 
     4     public Map<String, Command> getCommands() {
     5         if(commands == null){
     6             commands = new HashMap<String,Command>();
     7         }
     8         
     9         return commands;
    10     }
    11 
    12     public void setCommand(String key, Command command) {
    13         if(commands == null){
    14             commands = new HashMap<String,Command>();
    15         }
    16         commands.put(key, command);
    17     }
    18     
    19     public void RemoveCommand(String key) {
    20         commands.remove(key);
    21     }
    22 
    23     public void sail(String key){
    24         commands.get(key).sail();
    25     }
    26 }

      Client

     1 public class MainClass {
     2     public static void main(String[] args) {
     3         Peddler peddler = new Peddler();
     4         Command appleCommand = new AppleCommand(peddler);
     5         Command bananaCommand = new BananaCommand(peddler);
     6         
     7         Waiter waiter = new Waiter();
     8         waiter.setCommand("apple", appleCommand);
     9         waiter.setCommand("banana", bananaCommand);
    10         
    11         waiter.sail("apple");
    12         waiter.sail("banana");
    13         
    14         waiter.RemoveCommand("apple");
    15         
    16     }
    17 }

      这样,就完成了,一个命令模式的例子

      命令模式的优缺点

      优点: 1、降低了系统耦合度。

          2、新的命令可以很容易添加到系统中去。

      缺点:使用命令模式可能会导致某些系统有过多的具体命令类。

     
  • 相关阅读:
    Java 借助poi操作PDF工具类
    【ES】Java High Level REST Client 使用示例(增加修改)
    数据库表结构查询SQL
    MySQL windows中的存储备份
    jenkins + Ansible Plugin + ansi-color 让结果显示颜色
    jenkins 构建历史 显示版本号
    python 2.7.11 环境安装
    ansible 安装和使用
    豌豆夹Redis解决方案Codis安装使用
    Spark on Mesos部署
  • 原文地址:https://www.cnblogs.com/Renyi-Fan/p/11094545.html
Copyright © 2011-2022 走看看