面向对象的洗礼:设计模式(十六)之状态模式
状态模式是根据状态来执行不同的功能,通常以switch和if-ifelse来逻辑判断。面向对象设计,它的目的就是希望代码能够根据责任、功能来进行分解,不再是一大长串。状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂的时候,把状态的判断转移到表示不同状态的一系列类当中,把复杂的判断逻辑简化。
状态模式:当一个对象内在的状态改变时允许改变他的行为,这个对象看起来像是改变了其类。
当一个对象运行时,该执行什么方法,是取决于它的状态的时候,我们不用臃肿的条件判断语句,而是使用状态模式。
场景:人的行为,早上吃早饭,然后走路,上班,吃午饭,上班,走路,回家吃晚饭,睡觉。用条件控制来实现,if(time()==8点){ 吃早饭 }else if()....看看GoF的状态模式如何实现人的行为。以PHP为代码环境。
<?php class Person{ private $state; private $time; public function __construct(){ $this->state = new Breakfast(); } public function getTime(){ return $this->time; } public function setTime($time){ $this->time = $time; } public function getState(){ return $this->state; } public function setState($state){ $this->state = $state; } public function behavior(){ $this->state->behavior($this); } } class Breakfast{ public function behavior($personObj){ if($personObj->getTime() < 8){ echo '吃早餐<br>'; }else{ $personObj->setState(new Walk()); $personObj->behavior(); } } } class Walk{ public function behavior($personObj){ if($personObj->getTime() < 9 || ($personObj->getTime() > 18 && $personObj->getTime() < 19)){ echo '走路<br>'; }else{ if($personObj->getTime() > 9 && $personObj->getTime() < 18){ $personObj->setState(new Work()); $personObj->behavior(); }else{ $personObj->setState(new Dinner()); $personObj->behavior(); } } } } class Work{ public function behavior($personObj){ if($personObj->getTime() < 12 || ($personObj->getTime() > 13 && $personObj->getTime() < 18)){ echo '工作<br>'; }else{ if($personObj->getTime() < 13){ $personObj->setState(new Lunch()); $personObj->behavior(); }else{ $personObj->setState(new Walk()); $personObj->behavior(); } } } } class Lunch{ public function behavior($personObj){ if($personObj->getTime() < 13){ echo '吃午餐<br>'; }else{ $personObj->setState(new work()); $personObj->behavior(); } } } class Dinner{ public function behavior($personObj){ if($personObj->getTime() < 20){ echo '吃晚餐<br>'; }else{ $personObj->setState(new Sleep()); $personObj->behavior(); } } } class Sleep{ public function behavior($personObj){ echo '睡觉<br>'; exit; } } //客户端/接口 $personObj = new Person(); //时间表 $timeList = array(7, 8.5, 10, 12.5, 15, 18.5, 19.5); foreach($timeList as $time){ $personObj->setTime($time); $personObj->behavior(); }