您的位置:首页 > 编程语言 > PHP开发

PHP设计模式-策略模式

2014-02-02 16:11 721 查看
        什么事情是让程序员最苦恼的?就是需求不停地变。有时候一天要变好几次,要上线好几版程序。如果代码结构设计地不好,就会陷入无穷无尽的粪坑,不光改起来麻烦,而且容易有一堆的bug。我就亲身经历过这样痛苦的过程。自从使用了策略模式,应对各种策略的改变就游刃有余了。策略模式真有这么利害?至少,我觉得在应对指定的一些需求,策略的不断,策略模式的确能起到举足轻重的作用。

 那么什么是策略模式呢?如何使用呢?这个才是本文的重点。首先,我们来看个例子吧。有一个英语培训机构要给孩子们输导英语。主要有如下几种类型的课程(Course):口语,听力,语法。而学校是按课程系列(Serials)报班。学校从开建时期,只有一个课程系列,三种类型的课程都必须学.

class Serials
{

public function learnGrammar()
{
echo "学习语法";
}

public function learnListening()
{
echo "学习听力";
}

public function learnOral()
{
echo "学习口语";
}

public function learn()
{
$this->learnGrammar();
$this->learnListening();
$this->learnOral();
}

}        每个来学校学习的孩子们都是学同样的三种课程。这样貌似没什么问题,过了一段时间,有学生的家长提议说,我孩子口语挺好的,我只想让他重点学习语法和听力课程,可是现在的课程系列只有一个,必须三种都学。不仅浪费钱又浪费时间。学校领导也觉得,确实就一个课程系列显然满足不了学生们的需要,那就再开设三个课程系列,每个课程系列只上一种课程。

class GrammarSerials extends Serials
{
public function learnListening()
{

}

public function learOral()
{

}
}

class ListeningCourse extends Serials
{
public function learnGrammar()
{

}

public function learnOral()
{

}
}

class OralCourse extends Serials
{
public function learnListening()
{

}

public function learnGrammar()
{

}
}        只要把不需要的课程覆盖成空方法即可。很聪明的做法。这时候,又有学生和家长提意见了。如果我想要一个课程系列能够同时上口语课程,又能上语法课程。我们又再建立几个系列,把相应的不需要的课程覆盖掉?显然不合适。而且,又有学生和家长提建议了,我们的口语的课程能不能丰富点,可以搞个VIP一对一服务吗?这可怎么设计呢?那我们就得静下心来好好分析一下了。其实对于课程不管怎么变,都只有三种课程,它们的授课形式和内容都可能会有改变。那么,我们就先建立三个大类?这些大类都必须要能学习(废话)。并且我们建立三个普通课程和一个VIP口语课程。

interface Learning
{
public function learn();
}

class GrammarCourse implements Learning
{

public function learn()
{
echo "学习语法".PHP_EOL;
}
}

class OralCourse implements Learning
{

public function learn()
{
echo "学习口语".PHP_EOL;
}
}

class ListeningCourse implements Learning
{

public function learn()
{
echo "学习听力".PHP_EOL;
}
}

class NormalGrammerCourse extends GrammarCourse
{

}

class NormalOralCourse extends OralCourse
{

}

class NormalListeningCourse extends ListeningCourse
{

}

class VipOralCourse extends OralCourse
{
public function learn()
{
echo "1对1的口语教学".PHP_EOL;
}
}        而且我们知道,不管学校开设什么样的课程系列,都会只包括这三种大类型的课程。于是:

class Serials
{
protected $_grammarCourse;

protected $_listeningCourse;

protected $_oralCourse;

public function learn()
{
$this->_grammarCourse->learn();
$this->_listeningCourse->learn();
$this->_oralCourse->learn();
}
}        那如果我们有一个课程系列叫假日班,其中,语法和听力是正常上课,但口语是一对一服务。就定义如下。

class WeekendSubject extends Serials
{

public function __construct()
{
$this->_grammarCourse = new NormalGrammerCourse();
$this->_listeningCourse = new NormalListeningCourse();
$this->_oralCourse = new VipOralCourse();
}
}       这时,我们会发现,不管设立什么样的班系列,只要随意组合这三大类课程中的某一种课程就可以了。如果不存在的课程新建就可以了。这样灵活性很大。可以满足各种变化的需求,同时,添加新的课程时,只要新增一个类,并继承其相应的课程大类(口语,听力,语法)。这就是策略模式。这时候我们也能发现一个问题。我们的课程的初始化都是在班系列的构造函数中。而且直接指定了子类名。其实我们可以结合之前的工厂模式来处理。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: