zoukankan      html  css  js  c++  java
  • 不一样的命令模式(设计模式十五)

    前言

    什么是命令模式呢?其实是这样一个东西。

    “行为请求者”与“行为实现者”通常呈现一种“紧耦合”

    先介绍一下什么是行为请求者和行为实现者没有分开:

    class Person()
    {
      public void eat()
      {
          //吃饭
      }
      public void sleep()
      {
          //碎觉
      }
    }
    
    class ClientA()
    {
       public void do()
      {
         person.eat();
      }
    }
    

    这个是行为请求者和行为实现者没有分开。

    他们通过之间调用的方式,是一个紧耦合的关系。但是有些情况下,紧耦合并不适用。
    现在又一个一个客户:

    class ClientB()
    {
       public void do()
      {
         person.sleep();
      }
    }
    

    比如说,现在clientA和clientB 非常多,并且是一个并发多线程的过程,但是又不立即执行,比如说订单系统,要保持高响应。

    要达到这种目的就需要一个队列(当然也可以两个队列,但是如果person行为非常多,那么队列数量多的话难以维护),也就是说要把person.eat()和person.sleep()封装成一个具备公共接口或者公共父类对象。这就是命令模式的核心思想,把一个行为封装成一个对象。

    把概念贴一下:

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

    正文

    那么可以这样写,下面为手写,不一定完全正确。

    public abstract class Command
    {
       public abstract void excute();
    }
    
    public class EatCommand:Command
    {
       Peason peason;
       public EatCommand(Peason peason)
      {
        this.Person=Person
      }
      public void excute()
      {
        peason.eat();
      }
    }
    
    public class SleepCommand:Command
    {
       Peason peason;
       public SleepCommand(Peason peason)
      {
        this.Person=Person
      }
      public void excute()
      {
        peason.sleep();
      }
    }
    
    public class Manager
    {
       private static queue q=new queue();
       public Manager()
       {
    
       }
       public void add(Command command)
       {
            q.add(command);
       }
       public void excute()
      {
          if(q.Count!=0)
          {
             //不用担心这样写觉得command 会多余哈,编译器会帮我们优化,这样写更清晰
             var command=q.Dequeue() as Command;
             command.excute();
          }
      }
    }
    

    这里只写clientA:

    class ClientA()
    {
       public void do()
      {
         //不要关心person怎么来的,可以new 一个或者工厂实例化,等等
         EatCommand Eatcomment=new EatCommand(person);
         //manager 单例,在另外一个线程中消费
         manager.add(Eatcomment);
      }
    }
    

    这样写就是将一个行为变成了一个对象,而行为请求者和行为执行者,耦合性降低,这样灵活性就上升了。

    比如说,需要clientA 需要撤销功能。

    public void do()
    {
      EatCommand Eatcomment=new EatCommand(person);
      if(...)
      {
        manager.add(Eatcomment);
      }
      if(...)
      {
        manager.remove(Eatcomment);
     }
      manager.excute();
    }
    

    我这里没有实现remove,如果是这种的话,那么就不是一个队列而是一个集合或者别的。

    这样可以自由控制行为,而且可以延迟执行,延迟执行的优点可以参考linq。

    因为行为变成了对象,谁是执行者这个问题就弱化了(就是说当person传给了command,那么关注点和person就没有关系了),更多的关系到功能实现上了。

    缺点:
    使用命令模式可能会导致某些系统有过多的具体命令类。因为针对每一个命令都需要设计一个具体命令类,因此某些系统可能需要大量具体命令类,这将影响命令模式的使用。

  • 相关阅读:
    【Java每日一题】20161027
    【Java每日一题】20161026
    【Java每日一题】20161025
    【Java每日一题】20161024
    【Java每日一题】20161021
    【Java每日一题】20161020
    【Java每日一题】20161019
    Xen们和Open Stack们
    Linux内存管理子系统
    Python学习资料收集
  • 原文地址:https://www.cnblogs.com/aoximin/p/13616558.html
Copyright © 2011-2022 走看看