状态模式
状态模式说白了就是不同的状态,执行不同的行为,也就是状态和行为分离
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.结果
订单已经确认。
订单已经发货了。
订单已经完成。