1. 设计模式原理说明
状态模式(State Pattern) 是一种行为设计模式,它允许对象在其内部状态发生变化时改变其行为。这个模式的核心思想是使用不同的类来表示不同的状态,每个状态类都封装了与该状态相关的特定行为。当对象的状态发生改变时,对象会切换到另一个状态对象,从而改变了它的行为。
主要角色
- Context(上下文):定义客户感兴趣的接口,维护一个对当前状态对象的引用。
- State(抽象状态):定义一个接口,用以封装与Context的一个特定状态相关的行为。
- 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. 总结
状态模式 是一种行为设计模式,它允许对象在其内部状态发生变化时改变其行为。这个模式的核心思想是使用不同的类来表示不同的状态,每个状态类都封装了与该状态相关的特定行为。当对象的状态发生改变时,对象会切换到另一个状态对象,从而改变了它的行为。
主要优点
- 简化对象的操作:将与特定状态相关的行为封装在状态对象中,使上下文对象的操作更加简单。
- 高内聚低耦合:状态对象之间的转换逻辑被封装在状态对象内部,减少了上下文对象的复杂性。
- 易于扩展:新增状态时,只需添加新的状态类,而不需要修改现有的代码。
主要缺点
- 类的膨胀:每增加一个新的状态就需要增加一个新的类,可能导致类的数量急剧增加。
- 状态转换逻辑复杂:状态之间的转换逻辑可能变得复杂,尤其是当状态数量较多时。
适用场景
- 当一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变其行为时。
- 当控制一个对象的状态转换的条件表达式过于复杂时。
- 当代码中包含大量与对象状态有关的条件语句时,可以考虑使用状态模式来简化这些条件语句。