1. 简介
状态模式(State Pattern)是一种行为设计模式,通常使用它来实现有限状态机(Finite-State Machine),从而解决对象在不同状态下的行为差异问题,并且可以避免使用大量的条件语句来处理这些差异。
2. 模式结构
一个抽象的状态模式的UML关系图如下:
classDiagram
class Client {
+main()
}
class State {
<<interface>>
+handle()
}
class ConcreteState {
+handle()
}
class Context {
-state: State
+changeState(state: State)
+handle()
}
State <|.. ConcreteState
Context o-- State
Client ..> Context
Client ..> ConcreteState
- Context(上下文类) :维护一个指向状态对象的引用,这个引用定义了环境对象的当前状态。
- State(状态接口) :定义了一个接口,用于封装上下文的特定状态的行为。
- ConcreteState(具体状态类) :实现 State 接口,并定义具体状态的行为。
- CLient(客户端):调用上下文,并根据不同的条件切换上下文的状态。
3. 优缺点以及使用场景
优点:
- 封装性:状态相关的操作被封装在具体的状态类中,遵循单一职责原则。
- 可扩展性:新增状态时,只需增加相应的具体状态类,不会影响到其他类。
- 减少条件语句:避免在环境类中使用大量的条件语句来判断当前的状态。
缺点:
- 增加系统复杂性:对于简单的状态逻辑,使用状态模式可能会增加系统的复杂性。
- 增加对象数量:每个状态都需要一个具体的状态类,可能会增加系统中对象的数量。
应用场景:
- 对象的行为依赖于其状态,且状态有多种可能。
- 行为随状态改变而改变,且状态的改变会影响行为的逻辑。
4. 练习:【设计模式专题之状态模式】20-开关台灯
"""
【设计模式专题之状态模式】20-开关台灯
时间限制:1.000S 空间限制:256MB
题目描述
小明家有一个灯泡,刚开始为关闭状态(OffState)。台灯可以接收一系列的指令,包括打开("ON")、关闭("OFF")和闪烁("blink")。每次接收到一个指令后,台灯会执行相应的操作,并输出当前灯泡的状态。请设计一个程序模拟这个灯泡系统。
输入描述
第一行是一个整数 n(1 <= n <= 1000),表示接收的命令数量。
接下来的 n 行,每行包含一个字符串 s,表示一个命令("ON"、"OFF"或"blink")。
输出描述
对于每个命令,输出一行,表示执行该命令后灯泡的状态。
输入示例
5
ON
OFF
BLINK
OFF
ON
输出示例
Light is ON
Light is OFF
Light is Blinking
Light is OFF
Light is ON
"""
from abc import ABC, abstractmethod
class State(ABC):
@abstractmethod
def show(self):
raise NotImplemented
class OnState(State):
def __init__(self):
self.name = "ON"
def show(self):
print(f"Light is ON")
class OffState(State):
def __init__(self):
self.name = "OFF"
def show(self):
print(f"Light is OFF")
class BlinkState(State):
def __init__(self):
self.name = "BLINK"
def show(self):
print(f"Light is Blinking")
class Light:
def __init__(self, state: State):
self.state = state
def changeState(self, state: State):
self.state = state
def show(self):
if self.state:
self.state.show()
def client():
n = int(input())
light = Light(OffState())
for _ in range(n):
stateName = input()
if stateName == "ON":
state = OnState()
elif stateName == "OFF":
state = OffState()
else:
assert stateName == "BLINK"
state = BlinkState()
light.changeState(state)
light.show()
if __name__ == "__main__":
client()