设计模式:命令模式

其实这个应该挺好理解的,可以跟工厂模式,策略模式做个对比,工厂模式注重的是创建不同的对象,毕竟是创建型设计模式。策略模式是行为型设计模式,注重选择不同的策略以及对应后面的算法。命令模式跟二者结构很像,可以理解为在进一步的策略模式,直接根据一个简单的命令去执行后面对应的逻辑。

设计模式其实很多结构都是大同小异,因为毕竟语言特性也就那些,继承,实现,组合这些,再加上一些数据结构。很多区别就是后面的意图。
创建型针对的是对象的创建和管理,
结构型是关于这个结构的解耦,不要一坨,能够充分的复用,也就是DRY原则,do not repaet yousrself,一次且仅一次。
行为型则是对应行为设计和逻辑处理的解耦

Command Design Pattern 行为模式 GoF定义:

The command pattern encapsulates a request as an object, thereby
letting us parameterize other objects with different requests, queue
or log requests, and support undoable operations.

命令模式将请求(命令)封装为一个对象,这样可以使用不同的请求参数化其他对象(将不同请求依赖注入到其他对象),并且能够支持请求(命令)的排队执行、记录日志、撤销等(附加控制)功能。

代码同样通过游戏的demo


public interface Command {
  void execute();
}

public class GotDiamondCommand implements Command {
  // 省略成员变量

  public GotDiamondCommand(/*数据*/) {
    //...
  }

  @Override
  public void execute() {
    // 执行相应的逻辑
  }
}
//GotStartCommand/HitObstacleCommand/ArchiveCommand类省略

public class GameApplication {
  private static final int MAX_HANDLED_REQ_COUNT_PER_LOOP = 100;
  private Queue<Command> queue = new LinkedList<>();

  public void mainloop() {
    while (true) {
      List<Request> requests = new ArrayList<>();
      
      //省略从epoll或者select中获取数据,并封装成Request的逻辑,
      //注意设置超时时间,如果很长时间没有接收到请求,就继续下面的逻辑处理。
      
      for (Request request : requests) {
        Event event = request.getEvent();
        Command command = null;
        if (event.equals(Event.GOT_DIAMOND)) {
          command = new GotDiamondCommand(/*数据*/);
        } else if (event.equals(Event.GOT_STAR)) {
          command = new GotStartCommand(/*数据*/);
        } else if (event.equals(Event.HIT_OBSTACLE)) {
          command = new HitObstacleCommand(/*数据*/);
        } else if (event.equals(Event.ARCHIVE)) {
          command = new ArchiveCommand(/*数据*/);
        } // ...一堆else if...

        queue.add(command);
      }

      int handledCount = 0;
      while (handledCount < MAX_HANDLED_REQ_COUNT_PER_LOOP) {
        if (queue.isEmpty()) {
          break;
        }
        Command command = queue.poll();
        command.execute();
      }
    }
  }
}

这里有一个人总结的关于结构大差不差的设计模式对比很不错,摘抄一下:

单例模式和享元模式,缓存,静态工厂方法: 他们的共同点是:对象的复用 不同点: 应用享元模式是为了对象"共享使用",节省内存
而应用单例/多例模式是为了限制对象的个数 应用缓存是为了提高访问效率
应用对象池(数据库连接池,线程池)是为了对象的"重复使用"和管理,主要是为了节省时间 有一种方法叫 静态工厂方法,例如
Boolean.valueof(),不会在每次调用时返回一个新对象,而是复用已有的,这一点有点像享元模式

适配器,代理,装饰器,桥接,: 他们的共同点是:对方法的增强 不同点: 适配器模式的作用是"适配",通常用于适配不同的组件,新旧系统
桥接模式将接口部分和实现部分分离,使两者可以分别扩展 装饰者模式是对原始类功能进行增强,并且可以支持多次,多种增强
代理模式实现了代理类和原始类的解耦,使代理类可以用于增强不同的功能

策略模式与简单工厂模式,命令模式: 共同点:都有对if/else进行下沉 不同点:
策略模式根据运行时状态返回一个"策略"/“算法”,这些"策略"具有相同目的,比如BubbleSort、SelectionSort
都是为了实现排序 命令模式中不同的命令具有不同的目的,对应不同的处理逻辑,并且互相之间不可替换 而简单工厂更侧重返回一个创建的对象

桥接模式与服务提供者框架,静态工厂的辨析(来自effective java): 服务提供者框架是这样一个系统:
多个服务提供者实现一个服务,系统为服务提供者的客户端提供多个实现,并把它们从多个实现中解耦出来 它分为四部分:
服务接口:系统抽象出一个接口,交给服务提供者实现(JDBC中的connection即为服务接口)
提供者注册API:交给服务提供者注册自己的API
(Class.forName(),将自己的Driver类加载到JVM中,JDBC会查找该类并注册他的api)
服务访问API:是一个静态方法,供客户端获取服务实例(DriverManager.gtConnection()便是此处的静态工厂,它拿到的connection实例,其实是mysql包里的connection实现)
服务提供者接口:是服务接口实例的工厂对象(在此为mysql包内的Driver类)

在此处,桥接模式和静态工厂方法的使用,共同构成了服务提供者框架

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值