• 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏吧

不一样的命令模式(设计模式十五)

开发技术 开发技术 2周前 (09-08) 14次浏览

前言

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

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

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

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就没有关系了),更多的关系到功能实现上了。

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


喜欢 (0)