状态模式

状态模式

状态模式说白了就是不同的状态,执行不同的行为,也就是状态和行为分离

1.状态模式的本质

状态模式的本质:根据状态来分离和选择行为。

状态模式的本质是允许对象在其内部状态发生改变时改变其行为,而无需直接修改对象本身。它通过将状态封装成独立的状态类,并将状态的行为委托给表示不同状态的对象来实现。

通过封装状态和行为,实现对象状态的动态切换,并将状态的变化对外透明化。这种解耦状态和行为的设计思想使得代码更加灵活、可扩展和易于维护。

2.何时选用状态模式

建议在以下情况中选用状态模式。.

  • 当一个对象的行为随着其内部状态的改变而改变,并且这些状态转换较为复杂时,可以考虑使用状态模式。状态模式可以将每个状态及其相关的行为封装成独立的类,使得状态转换变得清晰明确,易于理解和维护。

  • 当对象有多个状态,并且这些状态之间的转换逻辑较为复杂,但又不希望通过使用大量的条件语句来实现状态转换时,可以考虑使用状态模式。状态模式可以通过将状态和状态转换的逻辑封装到不同的类中,使代码更加清晰、简洁和可扩展。

  • 当需要在运行时动态地改变对象的行为,并且希望能够轻松地添加新的状态和相应的行为时,可以考虑使用状态模式。状态模式通过增加新的具体状态类来扩展系统,符合开闭原则,对现有代码的影响较小。

3.优缺点

状态模式有以下优点。

  • 将状态和行为进行了解耦:状态模式将每个状态及其相关的行为封装成独立的类,使得状态和行为可以独立变化,互不影响。这样可以提高代码的可维护性和可扩展性。

  • 简化了条件语句:状态模式通过将状态转换的逻辑封装到具体状态类中,避免了大量的条件语句。这使得代码更加清晰、简洁和易于理解。

  • 增加新的状态和行为方便:由于状态模式将每个状态及其相关的行为封装成独立的类,因此在需要添加新的状态和相应的行为时,只需要创建新的具体状态类即可,而无需修改现有代码。这符合开闭原则,对现有代码的影响较小。

状态模式也有一个很明显的缺点,一个状态对应一个状态处理类,会使得程序引入太多的状态类,这样程序变得杂乱。

4.状态模式的结构

在这里插入图片描述

  • 环境(Context):环境对象包含一个当前状态对象,并在需要时将请求委托给当前状态对象来执行相应的行为。

  • 抽象状态(State):抽象状态定义了表示状态的接口,声明了各种可能的操作方法。

  • 具体状态(Concrete State):具体状态类实现了抽象状态接口,每个具体状态类表示对象的一种特定状态,并实现了相应状态下的操作方法。

5.实现

上下文中维护状态及转换状态

这里用一个借钱的例子:

  • 借钱3次以下:对方会告诉你没钱
  • 借钱3次-5次:对方不回你消息
  • 借钱5次以上:对方拉黑你

在这里插入图片描述

1.借钱接口及其实现

/**
 * @description:借钱状态接口
 */
public interface BorrowState {

    /**
     * 借钱
     * @param user 用户
     * @param stateManager 状态管理器
     */
    void borrowMoney(String user,StateManager stateManager);
}

/**
 * @description:正常借钱(3次以下)
 */
public class NormalBorrowState implements BorrowState{
    @Override
    public void borrowMoney(String user,StateManager stateManager) {
        System.out.println("对方也没钱啊-,-");
    }
}

/**
 * @description:重复借钱(3-5次)
 */
public class RepeatBorrowState implements BorrowState{
    @Override
    public void borrowMoney(String user,StateManager stateManager) {
        System.out.println("对方表示不想回你消息了-,-");
    }
}

/**
 * @description:恶意借钱(5次以上)
 */
public class BlackBorrowState implements BorrowState{
    @Override
    public void borrowMoney(String user,StateManager stateManager) {
        System.out.println("您已被对方拉黑-,-");
    }
}

2.状态管理器

/**
 * @description:状态管理器(context)
 */
public class StateManager {

    private BorrowState borrowState;

    //用户,借钱次数
    private Map<String, Integer> countMap = new HashMap<>();

    public void borrow(String user) {
        Integer count = countMap.get(user);
        if (count == null) {
            count = 0;
        }
        //次数+1
        count++;
        countMap.put(user, count);
        //先判断当前状态,根据状态转换不同的行为
        if (count >= 1 && count < 3) {
            borrowState = new NormalBorrowState();
        } else if (count >= 3 && count < 5) {
            borrowState = new RepeatBorrowState();
        } else if (count >= 5) {
            borrowState = new BlackBorrowState();
        }

        this.borrowState.borrowMoney(user, this);
    }
}

3.测试类

public class Client {

    public static void main(String[] args) {
        StateManager stateManager = new StateManager();
        for (int i = 0; i < 10; i++) {
            stateManager.borrow("张三");
        }
    }
}

4.结果
在这里插入图片描述

上下文中维护状态处理类中转换状态

1.借钱接口没变,修改其实现类

/**
 * @description:正常借钱(3次以下)
 */
public class NormalBorrowState implements BorrowState {
    @Override
    public void borrowMoney(String user, StateManager stateManager) {
        System.out.println("对方也没钱啊-,-");
        //取出状态,根据状态转换行为
        Integer count = stateManager.getCountMap().get(user);
        if (count >= 2 && count < 5) {
            stateManager.getStateMap().put(user, new RepeatBorrowState());
        }
    }
}

/**
 * @description:重复借钱(3-5次)
 */
public class RepeatBorrowState implements BorrowState{
    @Override
    public void borrowMoney(String user,StateManager stateManager) {
        System.out.println("对方表示不想回你消息了-,-");
        Integer count = stateManager.getCountMap().get(user);
        if (count >= 5) {
            stateManager.getStateMap().put(user, new BlackBorrowState());
        }
    }
}

/**
 * @description:恶意借钱(5次以上)
 */
public class BlackBorrowState implements BorrowState{
    @Override
    public void borrowMoney(String user,StateManager stateManager) {
        System.out.println("您已被对方拉黑-,-");
    }
}

2.状态管理器

/**
 * @description:状态管理器(context)
 */
@Getter
public class StateManager {

    //用户,借钱次数
    private Map<String, Integer> countMap = new HashMap<>();
    //用户,要执行的行为
    private Map<String, BorrowState> stateMap = new HashMap<>();

    public void borrow(String user) {
        Integer count = countMap.get(user);
        if (count == null) {
            count = 0;
        }
        //次数+1
        count++;
        //放入状态
        countMap.put(user, count);

        //取出行为
        BorrowState borrowState = stateMap.get(user);
        if (borrowState == null) {
            borrowState = new NormalBorrowState();
        }

        borrowState.borrowMoney(user, this);
    }
}

3.测试类

public class Client {

    public static void main(String[] args) {
        StateManager stateManager = new StateManager();
        for (int i = 0; i < 10; i++) {
            stateManager.borrow("张三");
        }
    }
}

4.结果
在这里插入图片描述

模拟订单状态

1.抽象状态类及其实现类

/**
 * 抽象状态类
 */
public abstract class OrderState {
    /**
     * 确认
     */
    public abstract void confirm();

    /**
     * 发货
     */
    public abstract void ship();

    /**
     * 完成
     */
    public abstract void complete();
}

/**
 * 支付订单状态
 */
public class PaidOrderState extends OrderState {
    @Override
    public void confirm() {
        System.out.println("订单已经确认。");
    }

    @Override
    public void ship() {
        System.out.println("StateHandler shipped.");
    }

    @Override
    public void complete() {
        System.out.println("在发货之前无法完成订单。");
    }
}

/**
 * 发货订单状态
 */
public class ShippedOrderState extends OrderState {
    @Override
    public void confirm() {
        System.out.println("订单已经确认。");
    }

    @Override
    public void ship() {
        System.out.println("订单已经发货了。");
    }

    @Override
    public void complete() {
        System.out.println("StateHandler completed.");
    }
}

/**
 * 完成订单状态
 */
public class CompletedOrderState extends OrderState {
    @Override
    public void confirm() {
        System.out.println("订单已经完成。");
    }

    @Override
    public void ship() {
        System.out.println("订单已经完成,无法发货。");
    }

    @Override
    public void complete() {
        System.out.println("订单已经完成。");
    }
}

2.状态处理服务

/**
 * 状态处理服务
 */
public class StateHandler {
    private Map<String, OrderState> stateMap = new HashMap<>();

    public StateHandler() {
        stateMap.put("ship", new ShippedOrderState());//已付款状态
        stateMap.put("paid", new PaidOrderState());// 已发货状态
        stateMap.put("complete", new CompletedOrderState());// 已完成状态
    }

    public void confirm(String state) {
        stateMap.get(state).confirm();
    }

    public void ship(String state) {
        stateMap.get(state).ship();
    }

    public void complete(String state) {
        stateMap.get(state).complete();
    }
}

3.测试类

public class Main {
    public static void main(String[] args) {
        StateHandler stateHandler = new StateHandler();

        stateHandler.confirm("paid");
        stateHandler.ship("ship");
        stateHandler.complete("complete");
    }
}

4.结果

订单已经确认。
订单已经发货了。
订单已经完成。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值