Java设计模式 三十 状态模式 + 策略模式

状态模式 + 策略模式

状态模式策略模式的结合是一种强大而灵活的设计模式组合,它们都通过将行为封装到对象中来改变系统的行为,但在使用目的和方式上有细微的区别。

  • 状态模式(State Pattern)用于根据对象的内部状态改变其行为,它通过将状态封装到不同的状态对象中来实现行为的改变。
  • 策略模式(Strategy Pattern)则用于在多个算法中选择一个,通过将不同的算法封装到策略对象中,客户端可以动态地切换算法。

两者的结合常用于需要根据不同的情境或状态选择不同的算法或行为的场景。结合这两种模式,可以在某个状态下选择合适的策略,或者根据状态的变化来动态切换策略。


1. 场景说明

这两种模式的结合适合以下场景:

  1. 状态驱动的算法选择: 在系统的某些状态下,选择不同的算法或行为,这种场景下可以使用状态模式来管理状态,使用策略模式来管理状态下的行为选择。
  2. 动态行为变化: 系统的行为不仅取决于当前状态,还需要动态选择不同的算法或策略进行处理。
  3. 复杂的状态与策略切换: 例如,游戏中的角色有不同的状态(如攻击、休息、行走等),而每个状态下又有不同的行为策略。

2. 示例场景:游戏角色状态与行为策略

假设我们正在设计一个游戏角色的状态管理系统,其中角色有不同的状态 (如攻击、休息、行走),而在每种状态下,角色的行为策略 (如攻击策略、移动策略)不同。我们使用状态模式 来管理角色的状态,使用策略模式来管理每个状态下的行为策略。


(1) 行为策略接口

首先定义一个行为策略接口,表示角色的行为策略。

java 复制代码
// 行为策略接口:角色行为的通用接口
public interface CharacterBehaviorStrategy {
    void performAction();  // 执行角色的行为
}

(2) 具体行为策略:攻击策略

角色在攻击状态下的行为策略。

java 复制代码
// 具体行为策略:攻击策略
public class AttackBehaviorStrategy implements CharacterBehaviorStrategy {
    @Override
    public void performAction() {
        System.out.println("角色进行攻击!");
    }
}

(3) 具体行为策略:行走策略

角色在行走状态下的行为策略。

java 复制代码
// 具体行为策略:行走策略
public class WalkBehaviorStrategy implements CharacterBehaviorStrategy {
    @Override
    public void performAction() {
        System.out.println("角色正在行走!");
    }
}

(4) 具体行为策略:休息策略

角色在休息状态下的行为策略。

java 复制代码
// 具体行为策略:休息策略
public class RestBehaviorStrategy implements CharacterBehaviorStrategy {
    @Override
    public void performAction() {
        System.out.println("角色正在休息!");
    }
}

(5) 状态接口

定义一个状态接口,用于描述角色的不同状态。

java 复制代码
// 状态接口:角色状态的通用接口
public interface CharacterState {
    void setBehavior(CharacterBehaviorStrategy behaviorStrategy);  // 设置行为策略
    void performAction();  // 执行当前状态下的行为
}

(6) 具体状态:攻击状态

角色处于攻击状态时,行为策略为攻击策略。

java 复制代码
// 具体状态:攻击状态
public class AttackState implements CharacterState {
    private CharacterBehaviorStrategy behaviorStrategy;

    public AttackState() {
        this.behaviorStrategy = new AttackBehaviorStrategy();
    }

    @Override
    public void setBehavior(CharacterBehaviorStrategy behaviorStrategy) {
        this.behaviorStrategy = behaviorStrategy;
    }

    @Override
    public void performAction() {
        behaviorStrategy.performAction();
    }
}

(7) 具体状态:行走状态

角色处于行走状态时,行为策略为行走策略。

java 复制代码
// 具体状态:行走状态
public class WalkState implements CharacterState {
    private CharacterBehaviorStrategy behaviorStrategy;

    public WalkState() {
        this.behaviorStrategy = new WalkBehaviorStrategy();
    }

    @Override
    public void setBehavior(CharacterBehaviorStrategy behaviorStrategy) {
        this.behaviorStrategy = behaviorStrategy;
    }

    @Override
    public void performAction() {
        behaviorStrategy.performAction();
    }
}

(8) 具体状态:休息状态

角色处于休息状态时,行为策略为休息策略。

java 复制代码
// 具体状态:休息状态
public class RestState implements CharacterState {
    private CharacterBehaviorStrategy behaviorStrategy;

    public RestState() {
        this.behaviorStrategy = new RestBehaviorStrategy();
    }

    @Override
    public void setBehavior(CharacterBehaviorStrategy behaviorStrategy) {
        this.behaviorStrategy = behaviorStrategy;
    }

    @Override
    public void performAction() {
        behaviorStrategy.performAction();
    }
}

(9) 角色类

角色类拥有一个当前状态,并且能够根据状态执行不同的行为策略。

java 复制代码
// 角色类:控制角色的状态和行为
public class Character {
    private CharacterState state;

    public Character() {
        // 默认状态为休息
        this.state = new RestState();
    }

    public void setState(CharacterState state) {
        this.state = state;
    }

    public void performAction() {
        state.performAction();  // 执行当前状态的行为
    }

    public void changeBehavior(CharacterBehaviorStrategy behaviorStrategy) {
        state.setBehavior(behaviorStrategy);  // 切换策略
    }
}

(10) 客户端代码

在客户端中,我们可以根据角色的状态来动态选择行为策略,并切换角色的状态。

java 复制代码
public class Client {
    public static void main(String[] args) {
        // 创建角色
        Character character = new Character();

        // 执行角色的初始行为(默认是休息状态)
        System.out.println("初始状态:");
        character.performAction();  // 角色正在休息!

        // 改变角色状态为攻击状态
        System.out.println("\n改变为攻击状态:");
        character.setState(new AttackState());
        character.performAction();  // 角色进行攻击!

        // 改变角色状态为行走状态
        System.out.println("\n改变为行走状态:");
        character.setState(new WalkState());
        character.performAction();  // 角色正在行走!

        // 改变角色行为策略(即使处于行走状态,切换为攻击策略)
        System.out.println("\n切换为攻击行为策略:");
        character.changeBehavior(new AttackBehaviorStrategy());
        character.performAction();  // 角色进行攻击!
    }
}

运行结果:
复制代码
初始状态:
角色正在休息!

改变为攻击状态:
角色进行攻击!

改变为行走状态:
角色正在行走!

切换为攻击行为策略:
角色进行攻击!

3. 优点

状态模式的优势:
  1. 根据状态变化行为: 状态模式使得对象的行为可以随内部状态的变化而变化,避免了使用大量的条件语句。
  2. 简化状态管理: 通过将不同的状态封装成不同的状态类,避免了复杂的状态转移逻辑,简化了代码。
  3. 易于扩展: 新状态可以通过添加新的状态类来扩展,不需要修改现有代码,符合开闭原则。
策略模式的优势:
  1. 算法封装: 策略模式通过将算法封装成策略对象,客户端可以根据需要动态选择策略。
  2. 避免多重条件语句: 策略模式避免了在代码中使用大量的条件判断来选择不同的行为。
  3. 易于扩展: 新的策略可以通过添加新的策略类来扩展,不需要修改现有的代码,符合开闭原则。
组合的优势:
  1. 灵活的行为选择: 在不同的状态下,角色可以选择不同的策略行为,同时状态和策略的切换是独立的,增强了系统的灵活性。
  2. 清晰的职责分离: 状态模式专注于管理状态的切换,策略模式专注于管理行为的选择,符合单一职责原则。
  3. 更高的可维护性: 通过状态和策略的组合,可以轻松扩展新的状态或行为,而不需要对现有代码做出修改。

4. 缺点

  1. 增加系统复杂性: 引入状态和策略类后,系统中的类数量增加,可能导致系统复杂性提升。
  2. 性能开销: 状态和策略的切换可能导致性能开销,尤其是在频繁切换状态或策略的情况下。

5. 应用场景

  1. 游戏开发 在游戏中,角色通常有多种状态(如行走、攻击、休息等),每种状态下有不同的行为策略。状态模式和策略模式结合可以方便地管理角色的状态和行为。
  2. 工作流管理: 在工作流系统中,不同的工作状态可能需要不同的处理策略,可以使用状态模式来管理状态,策略模式来选择处理算法。
  3. 订单处理系统: 订单在不同状态下(如待处理、已支付、已发货等)可能有不同的处理策略,结合状态和策略模式可以实现高效的订单处理逻辑。

6. 总结

状态模式 + 策略模式的结合为具有复杂状态和动态行为选择的系统提供了一个高效的解决方案。状态模式通过管理状态的变化来切换行为,而策略模式则通过封装不同的行为选择策略,使得系统在运行时能够根据当前状态灵活选择不同的算法或行为。

相关推荐
Coder码匠17 分钟前
Dockerfile 优化实践:从 400MB 到 80MB
java·spring boot
reddingtons7 小时前
【游戏宣发】PS “生成式扩展”流,30秒无损适配全渠道KV
游戏·设计模式·新媒体运营·prompt·aigc·教育电商·游戏美术
李慕婉学姐8 小时前
【开题答辩过程】以《基于JAVA的校园即时配送系统的设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
java·开发语言·数据库
奋进的芋圆9 小时前
Java 延时任务实现方案详解(适用于 Spring Boot 3)
java·spring boot·redis·rabbitmq
sxlishaobin10 小时前
设计模式之桥接模式
java·设计模式·桥接模式
model200510 小时前
alibaba linux3 系统盘网站迁移数据盘
java·服务器·前端
荒诞硬汉10 小时前
JavaBean相关补充
java·开发语言
提笔忘字的帝国10 小时前
【教程】macOS 如何完全卸载 Java 开发环境
java·开发语言·macos
2501_9418824810 小时前
从灰度发布到流量切分的互联网工程语法控制与多语言实现实践思路随笔分享
java·开发语言
華勳全栈11 小时前
两天开发完成智能体平台
java·spring·go