Bootstrap

【设计模式】【行为型模式(Behavioral Patterns)】之状态模式(State Pattern)

1. 设计模式原理说明

状态模式(State Pattern) 是一种行为设计模式,它允许对象在其内部状态发生变化时改变其行为。这个模式的核心思想是使用不同的类来表示不同的状态,每个状态类都封装了与该状态相关的特定行为。当对象的状态发生改变时,对象会切换到另一个状态对象,从而改变了它的行为。

主要角色
  1. Context(上下文):定义客户感兴趣的接口,维护一个对当前状态对象的引用。
  2. State(抽象状态):定义一个接口,用以封装与Context的一个特定状态相关的行为。
  3. ConcreteState(具体状态):实现State接口,每种状态都对应一个具体的状态类,封装了与该状态相关的特定行为。

2. UML 类图及解释

UML 类图
+-----------------+
|     Context     |
|-----------------|
| - state: State  |
| + setState(state: State) |
| + request()     |
+-----------------+
           ^
           |
           |
           v
+-----------------+
|     State       |
|-----------------|
| + handle(context: Context) |
+-----------------+
           ^
           |
           |
           v
+-----------------+
| ConcreteStateA  |
|-----------------|
| + handle(context: Context) |
+-----------------+
           ^
           |
           |
           v
+-----------------+
| ConcreteStateB  |
|-----------------|
| + handle(context: Context) |
+-----------------+
类图解释
  • Context:定义客户感兴趣的接口,维护一个对当前状态对象的引用。当状态变化时,调用setState方法更新当前状态。
  • State:定义一个接口,用以封装与Context的一个特定状态相关的行为。
  • ConcreteStateA 和 ConcreteStateB:实现State接口,每种状态都对应一个具体的状态类,封装了与该状态相关的特定行为。

3. 代码案例及逻辑详解

Java 代码案例
// 抽象状态
interface State {
    void handle(Context context);
}

// 具体状态 A
class ConcreteStateA implements State {
    @Override
    public void handle(Context context) {
        System.out.println("Current state is ConcreteStateA");
        context.setState(new ConcreteStateB());
    }
}

// 具体状态 B
class ConcreteStateB implements State {
    @Override
    public void handle(Context context) {
        System.out.println("Current state is ConcreteStateB");
        context.setState(new ConcreteStateA());
    }
}

// 上下文
class Context {
    private State state;

    public Context(State state) {
        this.state = state;
    }

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

    public void request() {
        state.handle(this);
    }
}

// 客户端
public class Client {
    public static void main(String[] args) {
        Context context = new Context(new ConcreteStateA());
        context.request();  // 输出: Current state is ConcreteStateA
        context.request();  // 输出: Current state is ConcreteStateB
    }
}
C++ 代码案例
#include <iostream>

// 抽象状态
class State {
public:
    virtual void handle(Context* context) = 0;
};

// 具体状态 A
class ConcreteStateA : public State {
public:
    void handle(Context* context) override {
        std::cout << "Current state is ConcreteStateA" << std::endl;
        context->setState(new ConcreteStateB());
    }
};

// 具体状态 B
class ConcreteStateB : public State {
public:
    void handle(Context* context) override {
        std::cout << "Current state is ConcreteStateB" << std::endl;
        context->setState(new ConcreteStateA());
    }
};

// 上下文
class Context {
private:
    State* state;
public:
    Context(State* state) : state(state) {}

    void setState(State* state) {
        delete this->state;
        this->state = state;
    }

    void request() {
        state->handle(this);
    }
};

// 客户端
int main() {
    Context* context = new Context(new ConcreteStateA());
    context->request();  // 输出: Current state is ConcreteStateA
    context->request();  // 输出: Current state is ConcreteStateB

    delete context;
    return 0;
}
Python 代码案例
# 抽象状态
class State:
    def handle(self, context):
        pass

# 具体状态 A
class ConcreteStateA(State):
    def handle(self, context):
        print("Current state is ConcreteStateA")
        context.set_state(ConcreteStateB())

# 具体状态 B
class ConcreteStateB(State):
    def handle(self, context):
        print("Current state is ConcreteStateB")
        context.set_state(ConcreteStateA())

# 上下文
class Context:
    def __init__(self, state):
        self.state = state

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

    def request(self):
        self.state.handle(self)

# 客户端
if __name__ == "__main__":
    context = Context(ConcreteStateA())
    context.request()  # 输出: Current state is ConcreteStateA
    context.request()  # 输出: Current state is ConcreteStateB
Go 代码案例
package main

import (
	"fmt"
)

// 抽象状态
type State interface {
	handle(context *Context)
}

// 具体状态 A
type ConcreteStateA struct{}

func (s *ConcreteStateA) handle(context *Context) {
	fmt.Println("Current state is ConcreteStateA")
	context.setState(&ConcreteStateB{})
}

// 具体状态 B
type ConcreteStateB struct{}

func (s *ConcreteStateB) handle(context *Context) {
	fmt.Println("Current state is ConcreteStateB")
	context.setState(&ConcreteStateA{})
}

// 上下文
type Context struct {
	state State
}

func (c *Context) setState(state State) {
	c.state = state
}

func (c *Context) request() {
	c.state.handle(c)
}

// 客户端
func main() {
	context := &Context{state: &ConcreteStateA{}}
	context.request()  // 输出: Current state is ConcreteStateA
	context.request()  // 输出: Current state is ConcreteStateB
}

4. 总结

状态模式 是一种行为设计模式,它允许对象在其内部状态发生变化时改变其行为。这个模式的核心思想是使用不同的类来表示不同的状态,每个状态类都封装了与该状态相关的特定行为。当对象的状态发生改变时,对象会切换到另一个状态对象,从而改变了它的行为。

主要优点
  1. 简化对象的操作:将与特定状态相关的行为封装在状态对象中,使上下文对象的操作更加简单。
  2. 高内聚低耦合:状态对象之间的转换逻辑被封装在状态对象内部,减少了上下文对象的复杂性。
  3. 易于扩展:新增状态时,只需添加新的状态类,而不需要修改现有的代码。
主要缺点
  1. 类的膨胀:每增加一个新的状态就需要增加一个新的类,可能导致类的数量急剧增加。
  2. 状态转换逻辑复杂:状态之间的转换逻辑可能变得复杂,尤其是当状态数量较多时。
适用场景
  • 当一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变其行为时。
  • 当控制一个对象的状态转换的条件表达式过于复杂时。
  • 当代码中包含大量与对象状态有关的条件语句时,可以考虑使用状态模式来简化这些条件语句。
;