• 创建型设计模式主要解决“对象的创建”问题
  • 结构型设计模式主要解决“类或对象的组合或组装”问题
  • 行为型设计模式主要解决的就是“类或对象之间的交互”问题

观察者模式

观察者模式也被称为发布订阅模式, 在对象之间定义一个一对多的依赖,当一个对象状态改变的时候,所有依赖的对象都会自动收到通知。

  1. public interface Subject {
  2. void registerObserver(Observer observer);
  3. void removeObserver(Observer observer);
  4. void notifyObservers(Message message);
  5. }
  6. public interface Observer {
  7. void update(Message message);
  8. }
  9. public class ConcreteSubject implements Subject {
  10. private List<Observer> observers = new ArrayList<Observer>();
  11. @Override
  12. public void registerObserver(Observer observer) {
  13. observers.add(observer);
  14. }
  15. @Override
  16. public void removeObserver(Observer observer) {
  17. observers.remove(observer);
  18. }
  19. @Override
  20. public void notifyObservers(Message message) {
  21. for (Observer observer : observers) {
  22. observer.update(message);
  23. }
  24. }
  25. }
  26. public class ConcreteObserverOne implements Observer {
  27. @Override
  28. public void update(Message message) {
  29. //TODO: 获取消息通知,执行自己的逻辑...
  30. System.out.println("ConcreteObserverOne is notified.");
  31. }
  32. }
  33. public class ConcreteObserverTwo implements Observer {
  34. @Override
  35. public void update(Message message) {
  36. //TODO: 获取消息通知,执行自己的逻辑...
  37. System.out.println("ConcreteObserverTwo is notified.");
  38. }
  39. }
  40. public class Demo {
  41. public static void main(String[] args) {
  42. ConcreteSubject subject = new ConcreteSubject();
  43. subject.registerObserver(new ConcreteObserverOne());
  44. subject.registerObserver(new ConcreteObserverTwo());
  45. subject.notifyObservers(new Message());
  46. }
  47. }

设计模式要干的事情就是解耦。
创建型模式是将创建和使用代码解耦,结构型模式是将不同功能代码解耦,行为型模式是将不同的行为代码解耦,具体到观察者模式,它是将观察者和被观察者代码解耦。

借助设计模式,我们利用更好的代码结构,将一大坨代码拆分成职责更单一的小类,让其满足开闭原则、高内聚松耦合等特性,以此来控制和应对代码的复杂性,提高代码的可扩展性。

模板模式

模板方法模式在一个方法中定义一个算法骨架,并将某些步骤推迟到子类中实现。模板方法模式可以让子类在不改变算法整体结构的情况下,重新定义算法中的某些步骤。

这里的“算法”,我们可以理解为广义上的“业务逻辑”,并不特指数据结构和算法中的“算法”。这里的算法骨架就是“模板”,包含算法骨架的方法就是“模板方法”,这也是模板方法模式名字的由来。

模板模式有两大作用:复用和扩展。其中,复用指的是,所有的子类可以复用父类中提供的模板方法的代码。扩展指的是,框架通过模板模式提供功能扩展点,让框架用户可以在不修改框架源码的情况下,基于扩展点定制化框架的功能。

  1. public abstract class AbstractClass {
  2. public final void templateMethod() {
  3. //...
  4. method1();
  5. //...
  6. method2();
  7. //...
  8. }
  9. protected abstract void method1();
  10. protected abstract void method2();
  11. }
  12. public class ConcreteClass1 extends AbstractClass {
  13. @Override
  14. protected void method1() {
  15. //...
  16. }
  17. @Override
  18. protected void method2() {
  19. //...
  20. }
  21. }
  22. public class ConcreteClass2 extends AbstractClass {
  23. @Override
  24. protected void method1() {
  25. //...
  26. }
  27. @Override
  28. protected void method2() {
  29. //...
  30. }
  31. }
  32. AbstractClass demo = ConcreteClass1();
  33. demo.templateMethod();

策略模式

策略模式定义一族算法类,将每个算法分别封装起来,让它们可以互相替换。策略模式可以使算法的变化独立于使用它们的客户端(这里的客户端代指使用算法的代码)。

通过策略模式来移除If/else或switch的分支判断逻辑
示例代码

  1. public class OrderService {
  2. public double discount(Order order) {
  3. double discount = 0.0;
  4. OrderType type = order.getType();
  5. if (type.equals(OrderType.NORMAL)) { // 普通订单
  6. //...省略折扣计算算法代码
  7. } else if (type.equals(OrderType.GROUPON)) { // 团购订单
  8. //...省略折扣计算算法代码
  9. } else if (type.equals(OrderType.PROMOTION)) { // 促销订单
  10. //...省略折扣计算算法代码
  11. }
  12. return discount;
  13. }
  14. }

使用策略模式+工厂方法模式优化后

  1. // 策略的定义
  2. public interface DiscountStrategy {
  3. double calDiscount(Order order);
  4. }
  5. // 省略NormalDiscountStrategy、GrouponDiscountStrategy、PromotionDiscountStrategy类代码...
  6. // 策略的创建
  7. public class DiscountStrategyFactory {
  8. private static final Map<OrderType, DiscountStrategy> strategies = new HashMap<>();
  9. static {
  10. strategies.put(OrderType.NORMAL, new NormalDiscountStrategy());
  11. strategies.put(OrderType.GROUPON, new GrouponDiscountStrategy());
  12. strategies.put(OrderType.PROMOTION, new PromotionDiscountStrategy());
  13. }
  14. public static DiscountStrategy getDiscountStrategy(OrderType type) {
  15. return strategies.get(type);
  16. }
  17. }
  18. // 策略的使用
  19. public class OrderService {
  20. public double discount(Order order) {
  21. OrderType type = order.getType();
  22. DiscountStrategy discountStrategy = DiscountStrategyFactory.getDiscountStrategy(type);
  23. return discountStrategy.calDiscount(order);
  24. }
  25. }

职责链模式

将请求的发送和接收解耦,让多个接收对象都有机会处理这个请求。将这些接收对象串成一条链,并沿着这条链传递这个请求,直到链上的某个接收对象能够处理它为止。

在职责链模式中,多个处理器(也就是刚刚定义中说的“接收对象”)依次处理同一个请求。一个请求先经过 A 处理器处理,然后再把请求传递给 B 处理器,B 处理器处理完后再传递给 C 处理器,以此类推,形成一个链条。链条上的每个处理器各自承担各自的处理职责,所以叫作职责链模式。

也可以有变种, 比如springSecurity, 经过所有的校验器, 只要有一个成功就成功.

示例代码:

  1. public interface IHandler {
  2. boolean handle();
  3. }
  4. public class HandlerA implements IHandler {
  5. @Override
  6. public boolean handle() {
  7. boolean handled = false;
  8. //...
  9. return handled;
  10. }
  11. }
  12. public class HandlerB implements IHandler {
  13. @Override
  14. public boolean handle() {
  15. boolean handled = false;
  16. //...
  17. return handled;
  18. }
  19. }
  20. public class HandlerChain {
  21. private List<IHandler> handlers = new ArrayList<>();
  22. public void addHandler(IHandler handler) {
  23. this.handlers.add(handler);
  24. }
  25. public void handle() {
  26. for (IHandler handler : handlers) {
  27. boolean handled = handler.handle();
  28. if (handled) {
  29. break;
  30. }
  31. }
  32. }
  33. }
  34. // 使用举例
  35. public class Application {
  36. public static void main(String[] args) {
  37. HandlerChain chain = new HandlerChain();
  38. chain.addHandler(new HandlerA());
  39. chain.addHandler(new HandlerB());
  40. chain.handle();
  41. }
  42. }

可以利用spring的IOC在HandlerChain做非常方便的构造方法注入:

  1. @Component
  2. public class HandlerChain {
  3. private final List<Handler> HANDLERS = new ArrayList<>();
  4. public HandlerChain(List<Handler> handlers) {
  5. HANDLERS.addAll(handlers);
  6. }
  7. public void handle() {
  8. for (Handler handler : HANDLERS) {
  9. if (handler.handle()) {
  10. break;
  11. }
  12. }
  13. }
  14. }

职责链模式在Servlet Filter中的应用
Servlet Filter 是 Java Servlet 规范中定义的组件
使用示例

  1. public class LogFilter implements Filter {
  2. @Override
  3. public void init(FilterConfig filterConfig) throws ServletException {
  4. // 在创建Filter时自动调用,
  5. // 其中filterConfig包含这个Filter的配置参数,比如name之类的(从配置文件中读取的)
  6. }
  7. @Override
  8. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
  9. System.out.println("拦截客户端发送来的请求.");
  10. chain.doFilter(request, response);
  11. System.out.println("拦截发送给客户端的响应.");
  12. }
  13. @Override
  14. public void destroy() {
  15. // 在销毁Filter时自动调用
  16. }
  17. }
  18. // 在web.xml配置文件中如下配置:
  19. <filter>
  20. <filter-name>logFilter</filter-name>
  21. <filter-class>com.xzg.cd.LogFilter</filter-class>
  22. </filter>
  23. <filter-mapping>
  24. <filter-name>logFilter</filter-name>
  25. <url-pattern>/*</url-pattern>
  26. </filter-mapping>

ApplicationFilterChain 类就是 Tomcat 提供的 FilterChain 的实现类,源码如下所示。

  1. public final class ApplicationFilterChain implements FilterChain {
  2. private int pos = 0; //当前执行到了哪个filter
  3. private int n; //filter的个数
  4. private ApplicationFilterConfig[] filters;
  5. private Servlet servlet;
  6. @Override
  7. public void doFilter(ServletRequest request, ServletResponse response) {
  8. if (pos < n) {
  9. ApplicationFilterConfig filterConfig = filters[pos++];
  10. Filter filter = filterConfig.getFilter();
  11. filter.doFilter(request, response, this);
  12. } else {
  13. // filter都处理完毕后,执行servlet
  14. servlet.service(request, response);
  15. }
  16. }
  17. public void addFilter(ApplicationFilterConfig filterConfig) {
  18. for (ApplicationFilterConfig filter:filters)
  19. if (filter==filterConfig)
  20. return;
  21. if (n == filters.length) {//扩容
  22. ApplicationFilterConfig[] newFilters = new ApplicationFilterConfig[n + INCREMENT];
  23. System.arraycopy(filters, 0, newFilters, 0, n);
  24. filters = newFilters;
  25. }
  26. filters[n++] = filterConfig;
  27. }
  28. }

职责链模式在Spring Interceptor中的应用
Servlet Filter 是 Servlet 规范的一部分,实现依赖于 Web 容器。Spring Interceptor 是 Spring MVC 框架的一部分,由 Spring MVC 框架来提供实现。客户端发送的请求,会先经过 Servlet Filter,然后再经过 Spring Interceptor,
使用示例

  1. public class LogInterceptor implements HandlerInterceptor {
  2. @Override
  3. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  4. System.out.println("拦截客户端发送来的请求.");
  5. return true; // 继续后续的处理
  6. }
  7. @Override
  8. public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
  9. System.out.println("拦截发送给客户端的响应.");
  10. }
  11. @Override
  12. public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  13. System.out.println("这里总是被执行.");
  14. }
  15. }
  16. //在Spring MVC配置文件中配置interceptors
  17. <mvc:interceptors>
  18. <mvc:interceptor>
  19. <mvc:mapping path="/*"/>
  20. <bean class="com.xzg.cd.LogInterceptor" />
  21. </mvc:interceptor>
  22. </mvc:interceptors>

HandlerExecutionChain 的源码如下

  1. public class HandlerExecutionChain {
  2. private final Object handler;
  3. private HandlerInterceptor[] interceptors;
  4. public void addInterceptor(HandlerInterceptor interceptor) {
  5. initInterceptorList().add(interceptor);
  6. }
  7. boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
  8. HandlerInterceptor[] interceptors = getInterceptors();
  9. if (!ObjectUtils.isEmpty(interceptors)) {
  10. for (int i = 0; i < interceptors.length; i++) {
  11. HandlerInterceptor interceptor = interceptors[i];
  12. if (!interceptor.preHandle(request, response, this.handler)) {
  13. triggerAfterCompletion(request, response, null);
  14. return false;
  15. }
  16. }
  17. }
  18. return true;
  19. }
  20. void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {
  21. HandlerInterceptor[] interceptors = getInterceptors();
  22. if (!ObjectUtils.isEmpty(interceptors)) {
  23. for (int i = interceptors.length - 1; i >= 0; i--) {
  24. HandlerInterceptor interceptor = interceptors[i];
  25. interceptor.postHandle(request, response, this.handler, mv);
  26. }
  27. }
  28. }
  29. void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex)
  30. throws Exception {
  31. HandlerInterceptor[] interceptors = getInterceptors();
  32. if (!ObjectUtils.isEmpty(interceptors)) {
  33. for (int i = this.interceptorIndex; i >= 0; i--) {
  34. HandlerInterceptor interceptor = interceptors[i];
  35. try {
  36. interceptor.afterCompletion(request, response, this.handler, ex);
  37. } catch (Throwable ex2) {
  38. logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
  39. }
  40. }
  41. }
  42. }
  43. }

那在项目开发中,类似权限这样的访问控制功能,我们该选择三者(AOP、Servlet Filter、Spring Interceptor)中的哪个来实现呢?有什么参考标准吗?

三者应用范围不同: web filter 作用于容器,应用范围影响最大;spring interceptor 作用于框架,范围影响适中;aop 作用于业务逻辑,精细化处理,范围影响最小。

状态模式

有限状态机,英文翻译是 Finite State Machine,缩写为 FSM,简称为状态机。状态机有 3 个组成部分:状态(State)、事件(Event)、动作(Action)。其中,事件也称为转移条件(Transition Condition)。事件触发状态的转移及动作的执行。不过,动作不是必须的,也可能只转移状态,不执行任何动作。

状态机示例:
设计模式: 行为型(上) - 图1
骨架代码:

  1. public enum State {
  2. SMALL(0),
  3. SUPER(1),
  4. FIRE(2),
  5. CAPE(3);
  6. private int value;
  7. private State(int value) {
  8. this.value = value;
  9. }
  10. public int getValue() {
  11. return this.value;
  12. }
  13. }
  14. public class MarioStateMachine {
  15. private int score;
  16. private State currentState;
  17. public MarioStateMachine() {
  18. this.score = 0;
  19. this.currentState = State.SMALL;
  20. }
  21. public void obtainMushRoom() {
  22. //TODO
  23. }
  24. public void obtainCape() {
  25. //TODO
  26. }
  27. public void obtainFireFlower() {
  28. //TODO
  29. }
  30. public void meetMonster() {
  31. //TODO
  32. }
  33. public int getScore() {
  34. return this.score;
  35. }
  36. public State getCurrentState() {
  37. return this.currentState;
  38. }
  39. }
  40. public class ApplicationDemo {
  41. public static void main(String[] args) {
  42. MarioStateMachine mario = new MarioStateMachine();
  43. mario.obtainMushRoom();
  44. int score = mario.getScore();
  45. State state = mario.getCurrentState();
  46. System.out.println("mario score: " + score + "; state: " + state);
  47. }
  48. }

状态机实现方式一:分支逻辑法

  1. public class MarioStateMachine {
  2. private int score;
  3. private State currentState;
  4. public MarioStateMachine() {
  5. this.score = 0;
  6. this.currentState = State.SMALL;
  7. }
  8. public void obtainMushRoom() {
  9. if (currentState.equals(State.SMALL)) {
  10. this.currentState = State.SUPER;
  11. this.score += 100;
  12. }
  13. }
  14. public void obtainCape() {
  15. if (currentState.equals(State.SMALL) || currentState.equals(State.SUPER) ) {
  16. this.currentState = State.CAPE;
  17. this.score += 200;
  18. }
  19. }
  20. public void obtainFireFlower() {
  21. if (currentState.equals(State.SMALL) || currentState.equals(State.SUPER) ) {
  22. this.currentState = State.FIRE;
  23. this.score += 300;
  24. }
  25. }
  26. public void meetMonster() {
  27. if (currentState.equals(State.SUPER)) {
  28. this.currentState = State.SMALL;
  29. this.score -= 100;
  30. return;
  31. }
  32. if (currentState.equals(State.CAPE)) {
  33. this.currentState = State.SMALL;
  34. this.score -= 200;
  35. return;
  36. }
  37. if (currentState.equals(State.FIRE)) {
  38. this.currentState = State.SMALL;
  39. this.score -= 300;
  40. return;
  41. }
  42. }
  43. public int getScore() {
  44. return this.score;
  45. }
  46. public State getCurrentState() {
  47. return this.currentState;
  48. }
  49. }

状态机实现方式二:查表法
设计模式: 行为型(上) - 图2

  1. public enum Event {
  2. GOT_MUSHROOM(0),
  3. GOT_CAPE(1),
  4. GOT_FIRE(2),
  5. MET_MONSTER(3);
  6. private int value;
  7. private Event(int value) {
  8. this.value = value;
  9. }
  10. public int getValue() {
  11. return this.value;
  12. }
  13. }
  14. public class MarioStateMachine {
  15. private int score;
  16. private State currentState;
  17. private static final State[][] transitionTable = {
  18. {SUPER, CAPE, FIRE, SMALL},
  19. {SUPER, CAPE, FIRE, SMALL},
  20. {CAPE, CAPE, CAPE, SMALL},
  21. {FIRE, FIRE, FIRE, SMALL}
  22. };
  23. private static final int[][] actionTable = {
  24. {+100, +200, +300, +0},
  25. {+0, +200, +300, -100},
  26. {+0, +0, +0, -200},
  27. {+0, +0, +0, -300}
  28. };
  29. public MarioStateMachine() {
  30. this.score = 0;
  31. this.currentState = State.SMALL;
  32. }
  33. public void obtainMushRoom() {
  34. executeEvent(Event.GOT_MUSHROOM);
  35. }
  36. public void obtainCape() {
  37. executeEvent(Event.GOT_CAPE);
  38. }
  39. public void obtainFireFlower() {
  40. executeEvent(Event.GOT_FIRE);
  41. }
  42. public void meetMonster() {
  43. executeEvent(Event.MET_MONSTER);
  44. }
  45. private void executeEvent(Event event) {
  46. int stateValue = currentState.getValue();
  47. int eventValue = event.getValue();
  48. this.currentState = transitionTable[stateValue][eventValue];
  49. this.score += actionTable[stateValue][eventValue];
  50. }
  51. public int getScore() {
  52. return this.score;
  53. }
  54. public State getCurrentState() {
  55. return this.currentState;
  56. }
  57. }

状态机实现方式三:状态模式

  1. public interface IMario { //所有状态类的接口
  2. State getName();
  3. //以下是定义的事件
  4. void obtainMushRoom();
  5. void obtainCape();
  6. void obtainFireFlower();
  7. void meetMonster();
  8. }
  9. public class SmallMario implements IMario {
  10. private MarioStateMachine stateMachine;
  11. public SmallMario(MarioStateMachine stateMachine) {
  12. this.stateMachine = stateMachine;
  13. }
  14. @Override
  15. public State getName() {
  16. return State.SMALL;
  17. }
  18. @Override
  19. public void obtainMushRoom() {
  20. stateMachine.setCurrentState(new SuperMario(stateMachine));
  21. stateMachine.setScore(stateMachine.getScore() + 100);
  22. }
  23. @Override
  24. public void obtainCape() {
  25. stateMachine.setCurrentState(new CapeMario(stateMachine));
  26. stateMachine.setScore(stateMachine.getScore() + 200);
  27. }
  28. @Override
  29. public void obtainFireFlower() {
  30. stateMachine.setCurrentState(new FireMario(stateMachine));
  31. stateMachine.setScore(stateMachine.getScore() + 300);
  32. }
  33. @Override
  34. public void meetMonster() {
  35. // do nothing...
  36. }
  37. }
  38. public class SuperMario implements IMario {
  39. private MarioStateMachine stateMachine;
  40. public SuperMario(MarioStateMachine stateMachine) {
  41. this.stateMachine = stateMachine;
  42. }
  43. @Override
  44. public State getName() {
  45. return State.SUPER;
  46. }
  47. @Override
  48. public void obtainMushRoom() {
  49. // do nothing...
  50. }
  51. @Override
  52. public void obtainCape() {
  53. stateMachine.setCurrentState(new CapeMario(stateMachine));
  54. stateMachine.setScore(stateMachine.getScore() + 200);
  55. }
  56. @Override
  57. public void obtainFireFlower() {
  58. stateMachine.setCurrentState(new FireMario(stateMachine));
  59. stateMachine.setScore(stateMachine.getScore() + 300);
  60. }
  61. @Override
  62. public void meetMonster() {
  63. stateMachine.setCurrentState(new SmallMario(stateMachine));
  64. stateMachine.setScore(stateMachine.getScore() - 100);
  65. }
  66. }
  67. // 省略CapeMario、FireMario类...
  68. public class MarioStateMachine {
  69. private int score;
  70. private IMario currentState; // 不再使用枚举来表示状态
  71. public MarioStateMachine() {
  72. this.score = 0;
  73. this.currentState = new SmallMario(this);
  74. }
  75. public void obtainMushRoom() {
  76. this.currentState.obtainMushRoom();
  77. }
  78. public void obtainCape() {
  79. this.currentState.obtainCape();
  80. }
  81. public void obtainFireFlower() {
  82. this.currentState.obtainFireFlower();
  83. }
  84. public void meetMonster() {
  85. this.currentState.meetMonster();
  86. }
  87. public int getScore() {
  88. return this.score;
  89. }
  90. public State getCurrentState() {
  91. return this.currentState.getName();
  92. }
  93. public void setScore(int score) {
  94. this.score = score;
  95. }
  96. public void setCurrentState(IMario currentState) {
  97. this.currentState = currentState;
  98. }
  99. }

实际上,上面的代码还可以继续优化,我们可以将状态类设计成单例,毕竟状态类中不包含任何成员变量。在这里,我们可以通过函数参数将 MarioStateMachine 传递进状态类。

  1. public interface IMario {
  2. State getName();
  3. void obtainMushRoom(MarioStateMachine stateMachine);
  4. void obtainCape(MarioStateMachine stateMachine);
  5. void obtainFireFlower(MarioStateMachine stateMachine);
  6. void meetMonster(MarioStateMachine stateMachine);
  7. }
  8. public class SmallMario implements IMario {
  9. private static final SmallMario instance = new SmallMario();
  10. private SmallMario() {}
  11. public static SmallMario getInstance() {
  12. return instance;
  13. }
  14. @Override
  15. public State getName() {
  16. return State.SMALL;
  17. }
  18. @Override
  19. public void obtainMushRoom(MarioStateMachine stateMachine) {
  20. stateMachine.setCurrentState(SuperMario.getInstance());
  21. stateMachine.setScore(stateMachine.getScore() + 100);
  22. }
  23. @Override
  24. public void obtainCape(MarioStateMachine stateMachine) {
  25. stateMachine.setCurrentState(CapeMario.getInstance());
  26. stateMachine.setScore(stateMachine.getScore() + 200);
  27. }
  28. @Override
  29. public void obtainFireFlower(MarioStateMachine stateMachine) {
  30. stateMachine.setCurrentState(FireMario.getInstance());
  31. stateMachine.setScore(stateMachine.getScore() + 300);
  32. }
  33. @Override
  34. public void meetMonster(MarioStateMachine stateMachine) {
  35. // do nothing...
  36. }
  37. }
  38. // 省略SuperMario、CapeMario、FireMario类...
  39. public class MarioStateMachine {
  40. private int score;
  41. private IMario currentState;
  42. public MarioStateMachine() {
  43. this.score = 0;
  44. this.currentState = SmallMario.getInstance();
  45. }
  46. public void obtainMushRoom() {
  47. this.currentState.obtainMushRoom(this);
  48. }
  49. public void obtainCape() {
  50. this.currentState.obtainCape(this);
  51. }
  52. public void obtainFireFlower() {
  53. this.currentState.obtainFireFlower(this);
  54. }
  55. public void meetMonster() {
  56. this.currentState.meetMonster(this);
  57. }
  58. public int getScore() {
  59. return this.score;
  60. }
  61. public State getCurrentState() {
  62. return this.currentState.getName();
  63. }
  64. public void setScore(int score) {
  65. this.score = score;
  66. }
  67. public void setCurrentState(IMario currentState) {
  68. this.currentState = currentState;
  69. }
  70. }

针对状态机,今天我们总结了三种实现方式。

  • 第一种实现方式叫分支逻辑法。

利用 if-else 或者 switch-case 分支逻辑,参照状态转移图,将每一个状态转移原模原样地直译成代码。对于简单的状态机来说,这种实现方式最简单、最直接,是首选。

  • 第二种实现方式叫查表法。

对于状态很多、状态转移比较复杂的状态机来说,查表法比较合适。通过二维数组来表示状态转移图,能极大地提高代码的可读性和可维护性。

  • 第三种实现方式叫状态模式。

对于状态并不多、状态转移也比较简单,但事件触发执行的动作包含的业务逻辑可能比较复杂的状态机来说,我们首选这种实现方式。

像游戏这种比较复杂的状态机,包含的状态比较多,我优先推荐使用查表法,而状态模式会引入非常多的状态类,会导致代码比较难维护。相反,像电商下单、外卖下单这种类型的状态机,它们的状态并不多,状态转移也比较简单,但事件触发执行的动作包含的业务逻辑可能会比较复杂,所以,更加推荐使用状态模式来实现。