状态模式从字面上其实并不是很好理解。这里的状态是什么意思呢?保存状态?那不就是备忘录模式了。其实,这里的状态是类的状态,通过改变类的某个状态,让这个类感觉像是换了一个类一样。说起来有点拗口吧,先学习概念之后再看。
GoF定义:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类
GoF类图
代码实现
class Context{ private $state; public function SetState(State $state): void { $this->state = $state; } public function Request(): void { $this->state = $this->state->Handle(); }}
class Context
{
private $state;
public function SetState(State $state): void
$this->state = $state;
}
public function Request(): void
$this->state = $this->state->Handle();
一个上下文类,也可以看作是目标类,它的内部有一个状态对象。当调用Request()的时候,去调用状态类的Handle()方法。目的是当前上下文类状态的变化都由外部的这个状态类来进行操纵。
interface State{ public function Handle(): State;}class ConcreteStateA implements State{ public function Handle(): State { echo '当前是A状态', PHP_EOL; return new ConcreteStateB(); }}class ConcreteStateB implements State{ public function Handle(): State { echo '当前是B状态', PHP_EOL; return new ConcreteStateA(); }}
interface State
public function Handle(): State;
class ConcreteStateA implements State
public function Handle(): State
echo '当前是A状态', PHP_EOL;
return new ConcreteStateB();
class ConcreteStateB implements State
echo '当前是B状态', PHP_EOL;
return new ConcreteStateA();
抽象状态接口及两个具体实现。这两个具体实现实际上是在相互调用。实现的效果就是上下文类每调用一次Request()方法,内部的状态类就变成别一个状态。就像一个开关,在打开与关闭中来回切换一样。
$c = new Context();$stateA = new ConcreteStateA();$c->SetState($stateA);$c->Request();$c->Request();$c->Request();$c->Request();
$c = new Context();
$stateA = new ConcreteStateA();
$c->SetState($stateA);
$c->Request();
客户端的实现,实例化上下文对象并设置初始的状态,然后通过不停的调用Request()对象来实现开关状态的切换。
我们的手机系统内定制了自己的商城系统,可以在手机上方便的下单购买我们的商品。一个订单(Context)会有多种状态(State),比如未支付、已支付、订单完成、订单退款等等一大堆状态。我们把这些状态都放在了对应的状态类里去实现,不同的状态类都会再去调用该状态下一步的动作,比如已支付后就等待收货、退款后就等待买家填写物流单号等,这样,状态模式就在我们的商城中被灵活的运用起来咯!!
完整代码:https://github.com/zhangyue0503/designpatterns-php/blob/master/22.state/source/state.php
通常的商城应用中都会有会员体系的存在,一般等级越高的会员可以享受的折扣也会越多,这个时候,运用状态模式就能很轻松的获得会员的等级折扣。当然,最主要的是,使用状态模式可以在需要添加或者删除会员等级时只添加对应的会员折扣状态子类就可以了。其他业务代码都不需要变动,我们一起来看看具体实现吧!
会员折扣图
完整源码:https://github.com/zhangyue0503/designpatterns-php/blob/master/22.state/source/state-member.php
<?phpclass Member{ private $state; private $score; public function SetState($state) { $this->state = $state; } public function SetScore($score) { $this->score = $score; } public function GetScore() { return $this->score; } public function discount() { return $this->state->discount($this); }}interface State{ public function discount($member);}class PlatinumMemeberState implements State{ public function discount($member) { if ($member->GetScore() >= 1000) { return 0.80; } else { $member->SetState(new GoldMemberState()); return $member->discount(); } }}class GoldMemberState implements State{ public function discount($member) { if ($member->GetScore() >= 800) { return 0.85; } else { $member->SetState(new SilverMemberState()); return $member->discount(); } }}class SilverMemberState implements State{ public function discount($member) { if ($member->GetScore() >= 500) { return 0.90; } else { $member->SetState(new GeneralMemberState()); return $member->discount(); } }}class GeneralMemberState implements State{ public function discount($member) { return 0.95; }}$m = new Member();$m->SetState(new PlatinumMemeberState());$m->SetScore(1200);echo '当前会员' . $m->GetScore() . '积分,折扣为:' . $m->discount(), PHP_EOL;$m->SetScore(990);echo '当前会员' . $m->GetScore() . '积分,折扣为:' . $m->discount(), PHP_EOL;$m->SetScore(660);echo '当前会员' . $m->GetScore() . '积分,折扣为:' . $m->discount(), PHP_EOL;$m->SetScore(10);echo '当前会员' . $m->GetScore() . '积分,折扣为:' . $m->discount(), PHP_EOL;
<?php
class Member
private $score;
public function SetState($state)
public function SetScore($score)
$this->score = $score;
public function GetScore()
return $this->score;
public function discount()
return $this->state->discount($this);
public function discount($member);
class PlatinumMemeberState implements State
public function discount($member)
if ($member->GetScore() >= 1000) {
return 0.80;
} else {
$member->SetState(new GoldMemberState());
return $member->discount();
class GoldMemberState implements State
if ($member->GetScore() >= 800) {
return 0.85;
$member->SetState(new SilverMemberState());
class SilverMemberState implements State
if ($member->GetScore() >= 500) {
return 0.90;
$member->SetState(new GeneralMemberState());
class GeneralMemberState implements State
return 0.95;
$m = new Member();
$m->SetState(new PlatinumMemeberState());
$m->SetScore(1200);
echo '当前会员' . $m->GetScore() . '积分,折扣为:' . $m->discount(), PHP_EOL;
$m->SetScore(990);
$m->SetScore(660);
$m->SetScore(10);
说明
关注公众号:【硬核项目经理】获取最新文章
添加微信/QQ好友:【xiaoyuezigonggong/149844827】免费得PHP、项目管理学习资料
知乎、公众号、抖音、头条搜索【硬核项目经理】
B站ID:482780532
原文链接:http://www.cnblogs.com/zyblog-coder/p/14245160.html
本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728