【设计模式】【行为型模式(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的一个特定状态相关的行为。
  • ConcreteStateAConcreteStateB:实现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. 状态转换逻辑复杂:状态之间的转换逻辑可能变得复杂,尤其是当状态数量较多时。
适用场景
  • 当一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变其行为时。
  • 当控制一个对象的状态转换的条件表达式过于复杂时。
  • 当代码中包含大量与对象状态有关的条件语句时,可以考虑使用状态模式来简化这些条件语句。
相关推荐
李广坤2 小时前
状态模式(State Pattern)
设计模式
李广坤4 小时前
观察者模式(Observer Pattern)
设计模式
李广坤4 小时前
中介者模式(Mediator Pattern)
设计模式
李广坤5 小时前
迭代器模式(Iterator Pattern)
设计模式
李广坤5 小时前
解释器模式(Interpreter Pattern)
设计模式
阿无,8 小时前
java23种设计模式之前言
设计模式
Asort9 小时前
JavaScript设计模式(八):组合模式(Composite)——构建灵活可扩展的树形对象结构
前端·javascript·设计模式
数据智能老司机9 小时前
数据工程设计模式——数据基础
大数据·设计模式·架构
nightunderblackcat10 小时前
四大名著智能可视化推演平台
前端·网络·爬虫·python·状态模式
笨手笨脚の11 小时前
设计模式-代理模式
设计模式·代理模式·aop·动态代理·结构型设计模式