本文目录导读:

是的,PHP中的状态模式(State Pattern)确实能够改变对象的行为,而且这正是它的核心作用。
状态模式允许一个对象在其内部状态改变时,改变它的行为,从外部看,就好像这个对象“换了个类”一样。
核心机制
状态模式将对象的行为封装到不同的“状态类”中,对象本身(称为“上下文” Context)持有一个对当前状态对象的引用,当条件发生变化时,上下文会切换到这个新状态对象,并将请求委托给它。
结果:同样的方法调用($context->doSomething()),由于当前状态不同,执行的具体逻辑也完全不同。
一个PHP示例
假设有一个文档对象(Document),它有“草稿”(Draft)、“审核中”(Moderation)和“已发布”(Published)三种状态,在每种状态下,publish() 方法的行为完全不同。
<?php
// 1. 状态接口
interface State {
public function publish(Document $document): void;
public function getStatus(): string;
}
// 2. 具体状态类
// 草稿状态
class DraftState implements State {
public function publish(Document $document): void {
// 草稿状态下,发布需要进入审核
echo "文档从草稿状态进入审核状态。\n";
$document->setState(new ModerationState());
}
public function getStatus(): string {
return "Draft";
}
}
// 审核中状态
class ModerationState implements State {
public function publish(Document $document): void {
// 审核通过,直接发布
echo "文档审核通过,已发布。\n";
$document->setState(new PublishedState());
}
public function getStatus(): string {
return "Moderation";
}
}
// 已发布状态
class PublishedState implements State {
public function publish(Document $document): void {
// 已发布的文档不能再发布
echo "错误:文档已经发布,无法再次发布。\n";
}
public function getStatus(): string {
return "Published";
}
}
// 3. 上下文类 (Document)
class Document {
private State $state;
public function __construct() {
// 初始状态为草稿
$this->state = new DraftState();
}
// 允许状态对象切换文档的状态
public function setState(State $state): void {
$this->state = $state;
}
// 关键方法:委托给当前状态对象
public function publish(): void {
$this->state->publish($this);
}
public function getStatus(): string {
return $this->state->getStatus();
}
}
// 4. 客户端使用
$doc = new Document();
echo "当前状态: " . $doc->getStatus() . "\n"; // 输出: Draft
$doc->publish(); // 第一次调用: 文档从草稿状态进入审核状态。
echo "当前状态: " . $doc->getStatus() . "\n"; // 输出: Moderation
$doc->publish(); // 第二次调用: 文档审核通过,已发布。
echo "当前状态: " . $doc->getStatus() . "\n"; // 输出: Published
$doc->publish(); // 第三次调用: 错误:文档已经发布,无法再次发布。
echo "当前状态: " . $doc->getStatus() . "\n"; // 输出: Published
关键变化点
在上述代码中,$doc 这个同一个对象调用了三次 publish() 方法:
- 第一次:状态是
DraftState,执行了“进入审核”的逻辑。 - 第二次:状态被切换为
ModerationState,执行了“审核发布”的逻辑。 - 第三次:状态被切换为
PublishedState,执行了“禁止发布”的逻辑。
对象的行为(publish() 的执行结果)完全随着状态的变化而动态改变。
为什么说它改变了对象行为?
与传统 if/else 或 switch 相比,状态模式的优点在于:
- 行为与状态分离:每种状态的行为被封装在自己的类中,而不是散落在多个
if分支里。 - 开闭原则:增加新状态非常容易(新增一个状态类),无需修改已有的状态类或上下文类。
- 消除大量条件判断:不再需要
if ($status == 'draft')这样的代码。 - 状态转换逻辑清晰:状态如何切换、从哪个状态切换到哪个状态,由每个状态类自己决定,逻辑集中且易于追踪。
是的,PHP状态模式的核心目的就是通过改变对象的内部状态来动态改变其行为,它让对象看起来像是“换了一种类型”,从而用更优雅、更面向对象的方式取代了复杂的条件分支逻辑。