设计模式-状态模式

2024-01-09 06:16:04
设计模式专栏


模式介绍

状态模式(State Pattern)是一种行为型设计模式,允许一个对象在其内部状态发生改变时改变其行为。在状态模式中,将与特定状态相关的行为局部化到一个状态中,并且将不同状态的行为分割开来,以满足“单一职责原则”。状态模式的核心是状态与行为绑定,不同的状态对应不同的行为。

状态模式的应用场景包括:

  1. 行为随状态改变而改变的场景。
  2. 一个操作中含有庞大的多分支结构,并且这些分支取决于对象的状态。

在实现状态模式时,通常包括环境类角色(Context)、抽象状态角色(IState)和具体状态角色(ConcreteState)三个角色。环境类角色(Context)定义客户端需要的接口,内部维护一个当前状态实例,并负责具体状态的切换;抽象状态角色(IState)定义该状态下的行为,可以有一个或多个行为;具体状态角色(ConcreteState)具体实现该状态对应的行为,并且在需要的情况下进行状态切换。

使用状态模式可以带来一些优点,例如结构清晰、状态转换明确、有利于程序扩展等。然而,使用状态模式也需要注意一些问题,例如会增加系统的类与对象的个数、实现较为复杂等。因此,在使用状态模式时需要谨慎考虑,避免过度使用或不当使用导致程序结构和代码的混乱。

在这里插入图片描述

模式特点

状态模式是一种对象行为型模式,其主要特点包括:

  1. 结构清晰:状态模式将与特定状态相关的行为局部化到一个状态中,并且将不同状态的行为分割开来,满足“单一职责原则”。这种设计使得程序的结构更加清晰,易于维护和扩展。
  2. 状态转换明确:状态模式将状态转换的逻辑封装在独立的对象中,使得状态转换更加明确,减少了对象间的相互依赖。这有助于提高代码的可读性和可维护性。
  3. 有利于程序的扩展:通过定义新的子类,可以很容易地增加新的状态和转换。这种设计使得程序易于扩展,能够适应需求的变化。
  4. 职责明确:状态类职责明确,每个状态类负责相应的行为,有利于程序的模块化和复用。
  5. 增加系统的类与对象的个数:状态模式的使用必然会增加系统的类与对象的个数,这可能会对程序的性能和内存占用产生一定的影响。
  6. 实现复杂度较高:状态模式的结构与实现都较为复杂,如果使用不当可能会导致程序结构和代码的混乱。因此,在应用状态模式时需要谨慎考虑,确保其适用性和正确性。

状态模式通过将与特定状态相关的行为局部化,减少对象间的相互依赖,使得程序的结构更加清晰、可维护和扩展。然而,它也增加了系统的复杂度,需要谨慎使用。

在这里插入图片描述

应用场景

状态模式的应用场景主要涉及到一个对象存在多个状态,且不同状态下行为不同的情况。以下是一些具体的应用场景:

  1. 与外部事件产生互动的对象:当一个对象的内部状态在接收到外部事件时会发生变化,从而使得系统的行为也随之发生变化。
  2. 具有多分支条件语句的操作:这些分支通常依赖于对象的状态。状态模式可以清晰地组织这些分支,使得代码更加可读和维护。
  3. 具有多种状态转换的情况:例如,一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。
  4. 存在多个动态变化的属性导致发生不同行为的对象:例如,电梯的运行状态和门的开关状态,当电梯处于运行状态时门不能打开,而当电梯停止后门才能打开。
  5. 需要模拟现实世界中的状态转换的情况:例如,购买物品时,将物品放入购物车并生成订单后可以进行付款。如果订单超过24小时后被关闭,此时订单取消,无法进行付款。

通过使用状态模式,可以使得代码更加清晰、可维护和可扩展,同时能够更好地模拟现实世界中的状态转换和行为变化。然而,需要注意的是,过度使用状态模式可能会导致代码复杂度增加,因此在使用时需要谨慎考虑其适用性和正确性。

在这里插入图片描述

状态模式和策略模式的区别

状态模式和策略模式是两种不同的设计模式,它们在实现方式、目的和应用场景等方面存在明显的区别。

  1. 状态模式策略模式的重点不同。状态模式重点在于状态之间的切换和对象行为的改变,而策略模式更侧重于根据具体情况选择不同的策略或算法。

  2. 状态模式涉及到的操作是基于状态的,而策略模式中不同的算法是互相独立的。状态模式的不同状态具有不同的行为,并且同一方法在不同状态下会执行不同的操作;而策略模式中的不同算法是互相独立的,它们只是被Context使用。

  3. 状态模式封装了对象的状态,而策略模式封装了算法或策略。状态模式将对象的状态封装在内部,通过改变对象的状态来改变其行为;而策略模式通过从Context中分离出策略或算法,使得算法可以被重用。

  4. 状态模式中的状态切换通常是自动的,而策略模式中的算法选择则需要手动进行。状态模式通过将状态切换的逻辑封装在子类中,使得状态的切换可以自动进行;而策略模式中需要手动调用相应的算法来实现处理逻辑。

  5. 状态模式通常涉及到对象的内部状态和行为,而策略模式更关注算法和策略的选择。状态模式关注的是对象的状态和行为的变化,以及如何通过状态的变化来改变行为;而策略模式更关注的是如何根据具体情况选择合适的算法或策略来解决问题。

状态模式和策略模式虽然都是行为型设计模式,但在具体实现和应用场景上存在一定的区别。在使用时需要根据具体的需求和场景选择合适的设计模式,以达到更好的设计效果。

在这里插入图片描述

代码示例

Java实现状态模式

在Java中实现状态模式,我们可以使用接口和类来实现。下面是一个简单的例子,描述了一个具有三种状态(State)的实体(Context)。

首先,我们定义一个状态接口(State):

public interface State {
    void handle(Context context);
}

然后,我们创建三种状态的具体实现(ConcreteState):

public class ConcreteStateA implements State {
    @Override
    public void handle(Context context) {
        System.out.println("执行状态A的行为");
        // 根据情况切换状态
        context.setState(new ConcreteStateB());
    }
}

public class ConcreteStateB implements State {
    @Override
    public void handle(Context context) {
        System.out.println("执行状态B的行为");
        // 根据情况切换状态
        context.setState(new ConcreteStateA());
    }
}

public class ConcreteStateC implements State {
    @Override
    public void handle(Context context) {
        System.out.println("执行状态C的行为");
        // 根据情况切换状态
        context.setState(new ConcreteStateA());
    }
}

接着,我们定义一个上下文类(Context),该类持有当前的状态,并调用该状态的方法:

public class Context {
    private State state;
    private final String entityId;

    public Context(String entityId) {
        this.entityId = entityId;
        this.state = new ConcreteStateA();  // 初始状态设置为状态A
    }

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

    public void request() {
        state.handle(this);  // 请求处理,调用当前状态的方法处理请求,并可能改变状态。
    }
}

最后,我们可以使用Context类来处理请求:

public class Main {
    public static void main(String[] args) {
        Context context = new Context("123");  // 创建上下文实例,设置初始状态为状态A。
        context.request();  // 请求处理,将执行状态A的行为,并切换到状态B。
        context.request();  // 请求处理,将执行状态B的行为,并切换到状态A。
        context.request();  // 请求处理,将执行状态A的行为,并切换到状态C。
        context.request();  // 请求处理,将执行状态C的行为,并切换到状态A。
    }
}

Python实现状态模式

在Python中实现状态模式的方式与Java中的实现方式类似。下面是一个简单的Python实现状态模式的示例:

class State:
    def handle(self, context):
        pass

class ConcreteStateA(State):
    def handle(self, context):
        print("执行状态A的行为")
        # 根据情况切换状态
        context.state = ConcreteStateB()

class ConcreteStateB(State):
    def handle(self, context):
        print("执行状态B的行为")
        # 根据情况切换状态
        context.state = ConcreteStateA()

class ConcreteStateC(State):
    def handle(self, context):
        print("执行状态C的行为")
        # 根据情况切换状态
        context.state = ConcreteStateA()

class Context:
    def __init__(self, entity_id):
        self.entity_id = entity_id
        self.state = ConcreteStateA()  # 初始状态设置为状态A

    def set_state(self, state):
        self.state = state

    def request(self):
        self.state.handle(self)  # 请求处理,调用当前状态的方法处理请求,并可能改变状态。

然后,我们可以使用Context类来处理请求:

if __name__ == "__main__":
    context = Context("123")  # 创建上下文实例,设置初始状态为状态A。
    context.request()  # 请求处理,将执行状态A的行为,并切换到状态B。
    context.request()  # 请求处理,将执行状态B的行为,并切换到状态A。
    context.request()  # 请求处理,将执行状态A的行为,并切换到状态C。
    context.request()  # 请求处理,将执行状态C的行为,并切换到状态A。

在这里插入图片描述

状态模式在spring中的应用

在Spring框架中,状态模式可以通过使用StateMachine实现。Spring StateMachine允许构建多个状态机,每个状态机可以处理不同的状态转换逻辑。通过使用Spring StateMachine,可以将状态转换的逻辑与具体业务逻辑分离,使得代码更加清晰和易于维护。

在Spring应用中,可以使用StateMachineBuilder来构建状态机。通过定义状态和状态之间的转换关系,可以构建出一个状态机。在每个状态下,可以定义相应的行为和事件处理逻辑。这样,当对象的状态发生变化时,可以自动触发相应的事件处理逻辑。

另外,Spring框架还提供了StateMachine的多种实现,例如SimpleStateMachineGenericStateMachine等。这些实现可以根据实际需求选择使用,以满足不同的状态转换需求。

在Spring框架中,可以通过使用状态模式和StateMachine实现来处理复杂的状态转换逻辑,使得代码更加清晰、可维护和可扩展。

在这里插入图片描述

设计模式-策略模式

文章来源:https://blog.csdn.net/zhangzehai2234/article/details/135469177
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。