状态模式从字面上其实并非很好理解。这里的状态是什么意思呢?保存状态?那不就是备忘录模式了。其实,这里的状态是类的状态,经过改变类的某个状态,让这个类感受像是换了一个类同样。提及来有点拗口吧,先学习概念以后再看。php
GoF定义:容许一个对象在其内部状态改变时改变它的行为。对象看起来彷佛修改了它的类git
GoF类图github
代码实现设计模式
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();
}
}
复制代码
抽象状态接口及两个具体实现。这两个具体实现其实是在相互调用。实现的效果就是上下文类每调用一次Request()方法,内部的状态类就变成别一个状态。就像一个开关,在打开与关闭中来回切换同样。学习
$c = new Context();
$stateA = new ConcreteStateA();
$c->SetState($stateA);
$c->Request();
$c->Request();
$c->Request();
$c->Request();
复制代码
客户端的实现,实例化上下文对象并设置初始的状态,而后经过不停的调用Request()对象来实现开关状态的切换。this
咱们的手机系统内定制了本身的商城系统,能够在手机上方便的下单购买咱们的商品。一个订单(Context)会有多种状态(State),好比未支付、已支付、订单完成、订单退款等等一大堆状态。咱们把这些状态都放在了对应的状态类里去实现,不一样的状态类都会再去调用该状态下一步的动做,好比已支付后就等待收货、退款后就等待买家填写物流单号等,这样,状态模式就在咱们的商城中被灵活的运用起来咯!!spa
完整代码:github.com/zhangyue050…架构设计
一般的商城应用中都会有会员体系的存在,通常等级越高的会员能够享受的折扣也会越多,这个时候,运用状态模式就能很轻松的得到会员的等级折扣。固然,最主要的是,使用状态模式能够在须要添加或者删除会员等级时只添加对应的会员折扣状态子类就能够了。其余业务代码都不须要变更,咱们一块儿来看看具体实现吧!设计
会员折扣图
<?php
class 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;
复制代码
说明
状态模式其实运用的范围很广,但使用的人确很少。毕竟if...else...更加的直观,并且大部分平常应用中的状态通常也不多会去修改或添加。若是你的订单状态须要常常的修改或添加,那确定在架构设计中存在着问题。可是,经过这个模式的学习,咱们看到了面向对象在处理这种问题时所展示的威力,这才是咱们对设计模式学习的最终目的,灵活合适地运用,更深刻的了解面向对象。好了,最后一个设计模式就要登场了,它就是访问者模式。