设计模式之 策略模式
策略模式(Strategy)
属于对象行为型设计模式,主要是定义一系列的算法,把这些算法一个个封装成拥有共同接口的单独的类,并且使它们之间可以互换。策略模式使这些算法在客户端调用它们的时候能够互不影响地变化。这里的算法不要狭义的理解为数据结构中算法,可以理解为不同的业务处理方法。
策略模式应用场景举例:
例1.
话说马上就要到清明节了,公司也放假了,人流量多了,各种商店的生意也好了,但为了加大节日销售的利润,各种商店纷纷出台了相应的打折策略,对于小点的商 店,商品相对较少,处理起来也不大费劲,但对于楼下的国美电器呀,附近的苏宁,这样的大店商品太多,打折信息也比较多,对于打折信息的记录当然就会采用一 些现代化的方法予以记录,假设有这么一个系统,他就用于处理此次的打折信息!可是,对于大店的他们经常会遇到打折的信息,并且每次的打折还都不一样,有时 候这些需要打折,哪些产品不需要,有时候打着多,有时候少,还有一些满消费多少就立减多少,有时候是满多少就送多少,这样每次操作起来一比较繁琐,于是他 们就想,能不能开发出来一些列的规则来,让这个系统对与不同的情况进行自动激活响应的策略规则,比如每到周六周日所有商品就打9折,每到法定节日就打8折,满1000元就送100元 的礼品,正在搞活动的商品买二送一等。当然,这需要事先把规则定义好,然后让计算机计算执行,可是事情该开始肯定是做不到十全十美的,我们以后有了新的产 品可能就会有新的促销策略,于是乎,就需要这个系统能够随时更改相应的规则并且可以随时加入新的规则,而这样的一个系统就实现了我们的策略模式,系统根据 不同的事务采取不同的策略执行,可随时添加新的策略执行……
例2.
比如在玩“极品飞车”这款游戏,那么游戏对车的轮胎是可以更换的,不同的轮胎在高速转弯时有不同的痕迹样式,那么针对“汽车”的配件“轮胎”就要可以变 化,而且轮胎和轮胎之间是可以相互替换的,这就是典型的要应用“策略模式”的场景!从程序结构中可以看到,完全符合了前面我们的要求:“灵活”,“顺序敏 感”。
什么是策略模式 策略模式有什么优点和原则
- 策略模式,又叫算法簇模式,就是定义了不同的算法族,并且之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
- 策略模式把会变化的内容取出并封装起来,以便以后可以轻易地改动或扩充部分,而不影响不需要变化的其他部分;
- 策略模式的好处在于你可以动态的改变对象的行为。
- 设计原则是把一个类中经常改变或者将来可能改变的部分提取出来,作为一个接口(c++中可以用虚类),然后在类中包含这个对象的实例,这样类的实例在运行时就可以随意调用实现了这个接口的类的行为。下面是一个例子。
- 策 略模式属于对象行为型模式,主要针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到 客户端的情况下发生变化。通常,策略模式适用于当一个应用程序需要实现一种特定的服务或者功能,而且该程序有多种实现方式时使用。
策略模式中有三个对象:
(1) 环境对象:该类中实现了对抽象策略中定义的接口或者抽象类的引用。
(2) 抽象策略对象:它可由接口或抽象类来实现。
(3) 具体策略对象:它封装了实现同不功能的不同算法。
利用策略模式构建应用程序,可以根据用户配置等内容,选择不同有算法来实现应用程序的功能。具体的选择有环境对象来完成。采用这种方式可以避免由于使用条件语句而带来的代码混乱,提高应用程序的灵活性与条理性。
程序例子:
// baseAgen类,抽象的基类
abstract class BaseAgent{
abstract function PrintPage();
}
//ieAgent类,用户端是IE时调用
class IeAgent extends BaseAgent{
public function PrintPage(){
return '当前浏览器是IE!';
}
}
//otherAgent类,用户端不是IE时调用
class OtherAgent extends BaseAgent{
public function PrintPage(){
return '当前浏览器不是IE!';
}
}
//判断并创建不同的对象类型,对象名为$currPage
if(strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE')){
$currPage = new IeAgent();
}else{
$currPage = new OtherAgent();
}
//输出
echo $currPage->PrintPage();
//上面程序在 IE 下的输出结果:
// 当前浏览器是IE!
/**
*
* 策略模式指的是程序中涉及决策控制的一种模式。例如,一段 PHP 代码用来显示一张 HTML 页面,访问者的浏览器可能会是 IE,也可能会是 Netscape。
* 这时程序就需要根据客户端浏览器的不同显示不同的网页内容。
* 策略模式通常通过定义一个抽象的基类,然后根据情况的不同创建不同的类继承这个基类。
* 接下来,根据实际情况的判断,对这个基类采用不同的方式进行继承。
*
* /
程序例子2:
/**
* 定义支持算法的接口
*
*/
abstract class Strategy
{
abstract public function AlgorithmInterface();
}
class ConcreateStratA extends Strategy
{
public function AlgorithmInterface()
{
echo "算法A";
}
}
class ConcreateStratB extends Strategy
{
public function AlgorithmInterface()
{
echo "算法B";
}
}
class ConcreateStratC extends Strategy
{
public function AlgorithmInterface()
{
echo "算法C";
}
}
class Context
{
private $_StrObj;
public function __construct($strobj)
{
$this->_StrObj = $strobj;
}
public function ContextInterface()
{
$this->_StrObj->AlgorithmInterface();
}
}
$context = new Context(new ConcreateStratA);
$context->ContextInterface();
$context = new Context(new ConcreateStratC);
$context->ContextInterface();
$context = new Context(new ConcreateStratB);
$context->ContextInterface();