前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >设计模式专题(二)——策略模式

设计模式专题(二)——策略模式

作者头像
用户1327360
发布2018-03-07 11:15:45
7220
发布2018-03-07 11:15:45
举报

设计模式专题(二)——策略模式

(原创内容,转载请注明来源,谢谢)

一、概述

1、含义

策略模式(Strategy)是一种定义了各类算法的模式,其将各种算法分别封装起来,在需要的时候去拉取各种算法,但并不影响使用算法的客户,实现让算法和对象分开来,使得算法可以独立于使用它的客户而变化。当执行某件事时,各类算法都可能用到,且变化性比较大,就适用于策略模式。

2、基本规则

1)策略模式定义的各种算法应该是完成同样的一件事,但是允许输入的内容不同,返回的结果也可以不同。

例如商场的营销策略,有可能出现打折、满减、买赠、积分、优惠券折扣等,每种策略是一种算法,假设原价100,经过不同的算法会得到不同的结果,且不同的算法需要输入的内容不同,如打折需要输入折扣,满减需要输入满多少减多少等。

2)策略模式可以与简单工厂模式结合,这样可以仅传入策略的名称与一些初始值,有策略类自动匹配相应的算法,并返回结果。

3、优点

1)策略模式的各个算法完全分开,互不影响,一个算法有问题也不影响其他算法以及程序非调用此算法的流程,并于故障判定与解决。

2)将客户端与服务端分隔开,客户端不需要进行大量的判断,而将判断交与服务端,而服务端做完判断去调不同的服务算法,也不必亲自逐个实现算法,因此实现了各模块的解耦与分离。

3)当分析过程中需要在不同场景、不同时间下调用不同的业务规则,就可以用策略模式来解决。

4)基本策略模式中,选择的具体实现需要客户端承担。但结合简单工厂模式后,则将选择交由服务端来实现。

4、缺点

1)维护各个策略类会给开发带来额外开销,需要开发人员对每个策略非常熟悉,如果经过几轮人员轮换,有可能导致每个人来开发都自己再编写一个策略,导致失去其意义。

2)使用策略人员需要对每个策略都非常熟悉,且明确知道其输入输出、适用场景、不适用场景,这样无形中增加学习成本。

不过上述两缺点可以在团队开发过程中,通过完善开发文档,加强团队交流的方式以避免。

5、策略模式与简单工厂模式的区别

策略模式是输入策略返回结果,工厂模式是输入想要的结果返回工厂生产的对象,两者很相似,有细微的不同。

1)工厂模式和策略模式的区别在于实例化一个对象的位置不同,对工厂模式而言,实例化对象是放在服务端的,即放在了工厂类里面;而策略模式实例化对象的操作在客户端,服务端的“销售部门”只负责传递该对象,并在服务端的环境里执行特定的操作。

2)、工厂模式根据条件生产出产品给客户端用。而策略模式是客户端将策略以参数形式传给服务端,传入策略的不同,调用同样方法得到的结果也不同。

6、策略模式类图(图片来自网络)

二、业务分析

下面用策略模式实现通过不同的场景调用不同的排序算法。

1、场景

现有三种排序算法:并归排序、快速排序、基数排序。当数据要求稳定(两个相等的数字在数组的前后位置经过排序后不变)、借用空间较小时,使用并归排序;当数据没有稳定性要求,且要速度较快时,可以使用快速排序;当不仅有数字,还有字母、其他符号等,需要通过自定义规则进行排序时,基数排序是最佳选择。

2、实现过程

1)定义抽象类,其规定一个方法是排序,所有继承此抽象类的都要有此方法。

abstract classSortArray{
         public abstract arrSort(array $arr);
}

2)定义各排序类,都继承SortArray

并归排序类:classMergeSort extends SortArray,快速排序类:class QuickSort extends SortArray,基数排序类:class BaseNumSortextends SortArray。这三个排序算法详见数据结构中排序算法部分的文章,不在此实现。

要求:各排序类的排序方法名称都叫arrSort,即实现抽象父类的方法。

3)定义策略类,用于调用排序算法

classStrategy{
private $sortStrategy;//用于确定调用哪一种排序类
//实例化strategy类时,需要传入参数,以判断是哪种策略。
public function __construct($type){
$arrAllowType = array(‘merge’,‘quick’, ‘base’);//自定义允许的策略,防止错误
if(!in_array($type,$arrAllowType)){
echo ‘strategy is notfound’;
exit;
}
$this->sortStrategy = $type;
return $this;
}
//策略选择,并返回结果
public function getSortedArray(array $arr){
         if(empty($arr)){
         return $arr;
}
//此处为结合了工厂类的策略模式,通过用户选择的策略实例化不同的类
//$sortClass:用于确定是哪一种排序类的实例,其为instanceof SortArray类,即要求是抽象类或其子类的实例。
switch($this->sortStrategy){
         case ‘merge’:  $sortClass = new MergeSort(); break;
         case ‘quick’:   $sortClass = new QuickSort(); break;
case ‘base:    $sortClass = new BaseNumSort(); break;
default: return $arr;//如果没有正确的类型,排序失败,直接返回原数组
}
//利用生成的类去调用其各自的arrSort()方法,获取排序好的结果
$sort = new $sortClass($arr);
return $sort-> arrSort();
}
}

4)客户端,调用策略获取排序结果

$arrToSort =array(1, 2, 5, 7, 17, 35, 40, 12, 17, 8, 59, 67, 34, 22, 15);
$type = ‘quick’;
$sortStrategy =new Strategy($type);
return$sortStrategy->getSortedArray($arrToSort);

——written by linhxx 2017.07.27

相关阅读:

设计模式专题(一)——面向对象的设计原则

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

本文分享自 决胜机器学习 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 设计模式专题(一)——面向对象的设计原则
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档