前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >PHP设计模式——状态模式

PHP设计模式——状态模式

作者头像
Lemon黄
发布2019-11-15 16:11:30
发布2019-11-15 16:11:30
48800
代码可运行
举报
文章被收录于专栏:Lemon黄Lemon黄
运行总次数:0
代码可运行

允许对象在其内部状态更改时更改其行为。该对象似乎将更改其类。

John在一家受欢迎的电话支持公司中担任客户支持代表。在以客户服务为导向的公司中,公司的首要任务是确保客户满意。为了改善服务质量,该公司投入了大量资金来改善支持代表的服务。最近的研究表明,支持代表的情绪会影响他们在工作中的表现。John本人承认,接听电话时的前几句话通常可以表明他所处的心情。当他心情愉快时,通常会向顾客打招呼“嗨!”或“你好,怎么样”。我可以帮您吗?”当他生气且情绪低落时,他的回答是打招呼“你好”或“是?”。如果John情绪温和,则他将用“嗨”或“你好”柔和的和一个人打开对话。

让我们将以上的信息放入代码中:

代码语言:javascript
代码运行次数:0
复制
class SupportRep
{
    private $_state =  "happy";
    public function setState($state)
    {
        $this->_state = $state;
    }
 
    public function sayHi()
    {
        if ($this->_state=='happy') {
            echo 'hi there!';
        } else if ($this->_state=='angry') {
            echo 'yes?';
        } else if ($this->_state=='moderate') {
            echo 'hi';
        }
    }
}

上面的代码非常简单明了,可以帮助我们研究支持代表的行为。但是,随着研究的进展和更多信息的引入,该代码可能还不够。研究表明,一个人的情绪会根据他打过的电话的数量以及当前的情绪而改变。

当John接听五到十个电话时,他的心情将从“快乐”变为“温和”,这可能是因为他感到疲倦或承受着压力。如果他接到10个以上的电话,他的心情将从“温和”变为“愤怒”,处理太多的支持电话确实很麻烦。

让我们重新编写代码以添加以上的逻辑:

代码语言:javascript
代码运行次数:0
复制
class SupportRep
{
    private $_state =  null;
    public  $numOfCalls = 0;
    public function setState($state)
    {
        $this->_state = $state;
    }
 
    public function sayHi()
    {
        if ($this->_state=='happy') {
            echo 'hi there!';
            if ($this->numOfCalls>5&&$this->numOfCalls<10) {
                $this->setState('moderate');
            }
            if ($this->numOfCalls>10) {
                $this->setState('angry');
            }
        } else if ($this->_state=='angry') {
            echo 'yes?';
        } else if ($this->_state=='moderate') {
            echo 'hi';
            if ($this->numOfCalls>10) {
                $this->setState('angry');
            }
        }
        $this->numOfCalls;
    }
}

你发现上面的代码有什么问题吗?不,它没有什么错,除了一堆的if-else的语句。对于我们来说,它甚至看起来都不是面向对象的,最糟糕的是它明显违反了单一责任原则(SRP)。此类更改的原因有多种。当你对快乐状态,温和状态或愤怒状态有其他逻辑时。它引入了代码修改,并且记住我们在这里只是在谈论sayHi()函数。当基于情绪的条件适用于其他岗位的各个方面时,会发生什么?

是时候改变了。在这种情况下,我们就需要使用状态模式(State Pattern)。状态模式使我们可以封装变化的部分,即sayHi函数。具体取决于支持代表的心情。

首先,让我们创建一个状态接口(StateInterface),所有后续状态都必须实现它:

代码语言:javascript
代码运行次数:0
复制
interface StateInterface
{
   public function sayHi();
}

然后,我们将创建三个状态的类,每个类都实现自己的逻辑:

代码语言:javascript
代码运行次数:0
复制
class AngryState implements StateInterface
{
    private $_supportRep = null;
    public function __construct(SupportRep $supportRep)
    {
        $this->_supportRep = $supportRep;
    }
    public function sayHi()
    {
        echo 'yes?';
    }
}
 
class ModerateState implements StateInterface
{
    private $_supportRep = null;
    public function __construct(SupportRep $supportRep)
    {
        $this->_supportRep = $supportRep;
    }
    public function sayHi() {
        echo 'hi';
        if ($this->_supportRep->numOfCalls>10) {
            $this->_supportRep->setState(new AngryState($this->_supportRep
        ));
        }
    }
}
 
class HappyState implements StateInterface
{
    private $_supportRep = null;
    public function __construct(SupportRep $supportRep)
    {
        $this->_supportRep = $supportRep;
    }
 
    public function sayHi()
    {
        echo 'hi there!';
        if ($this->_supportRep->numOfCalls>5&&$this->_supportRep->numOfCalls<10) {
        Rep));
    ));
    }
}

最后,我们来重构下支持代表的类SupportRep

代码语言:javascript
代码运行次数:0
复制
class SupportRep
{
    private $_state =  null;
    public  $numOfCalls = 0;
    public function __construct()
    {
        $this->_state = new ModerateState($this);
    }
 
    public function setState($state)
    {
        $this->_state = $state;
    }
 
    public function sayHi()
    {
        $this->_state->sayHi();
        $this->numOfCalls++;
    }
}

如你所见,SupportRep类的sayHi()函数将其职责委托给状态类。它不再违反单一责任原则(SRP)。三个状态类仍然可以通过组合来更改主要类的状态。

现在,SupportRep变得更加整洁,如果需要添加任何其他逻辑,则可以将其作为单独的状态类来完成。 SupportRep的其他功能可以委托给状态类。

在我们的示例中,状态模式允许对象(SupportRep对象)在其内部状态更改(在HappyStateModerateStateAngryState之间切换)时更改其行为(各个状态类中的sayHi()函数)。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-11-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Lemon黄 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档