2. 账户状态变更与生命周期管理
任务目标
在账户对象上实现状态机:正常(ACTIVE)、冻结(FROZEN)、已销户(CLOSED)。支持冻结、解冻、销户三个操作,每次变更写入状态变更日志(含时间、原状态、新状态、原因)。非法变更(如已销户再冻结、冻结中销户)必须被拒绝。
状态机规则
- ACTIVE → FROZEN(冻结)、ACTIVE → CLOSED(销户)
- FROZEN → ACTIVE(解冻)、FROZEN → CLOSED(销户)
- CLOSED 为终态,不允许任何变更
完整实现(Python)
from dataclasses import dataclass, field
from datetime import datetime
from enum import Enum
class Status(Enum):
ACTIVE = "ACTIVE"
FROZEN = "FROZEN"
CLOSED = "CLOSED"
# 合法状态迁移表:{原状态: {允许的新状态}}
TRANSITIONS = {
Status.ACTIVE: {Status.FROZEN, Status.CLOSED},
Status.FROZEN: {Status.ACTIVE, Status.CLOSED},
Status.CLOSED: set(),
}
@dataclass
class ChangeLog:
time: str
from_status: Status
to_status: Status
reason: str
@dataclass
class Account:
account_id: str
status: Status = Status.ACTIVE
logs: list = field(default_factory=list)
def _change(self, target: Status, reason: str) -> None:
if target not in TRANSITIONS[self.status]:
raise ValueError(
f"非法状态变更: {self.status.value} -> {target.value}"
)
self.logs.append(ChangeLog(
time=datetime.now().isoformat(timespec="seconds"),
from_status=self.status,
to_status=target,
reason=reason,
))
self.status = target
def freeze(self, reason: str) -> None:
self._change(Status.FROZEN, reason)
def unfreeze(self, reason: str) -> None:
self._change(Status.ACTIVE, reason)
def close(self, reason: str) -> None:
self._change(Status.CLOSED, reason)
if __name__ == "__main__":
acc = Account("A1001")
acc.freeze("司法冻结")
acc.unfreeze("冻结解除")
acc.close("客户销户")
for log in acc.logs:
print(f"{log.time} {log.from_status.value}->{log.to_status.value} ({log.reason})")
print("最终状态:", acc.status.value)
# 验证非法变更被拒绝
try:
acc.freeze("再次冻结")
except ValueError as e:
print("已拒绝:", e)
运行与验证
环境:Python 3.10+,无第三方依赖。保存为 account.py 后执行 python account.py。
通过条件:
- 打印出 3 条日志,依次为 ACTIVE→FROZEN、FROZEN→ACTIVE、ACTIVE→CLOSED,且每条含时间与原因;
- 最终状态为
CLOSED; - 对已销户账户再次冻结时抛出
ValueError,被except捕获并打印“已拒绝: 非法状态变更: CLOSED -> FROZEN”。
扩展验证:可对 FROZEN 状态直接调用 close(),应成功;对 CLOSED 调用 unfreeze() 应被拒绝。