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

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

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

一、概述

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

相关阅读:

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

原文发布于微信公众号 - 决胜机器学习(phpthinker)

原文发表时间:2017-07-27

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏腾讯Bugly的专栏

那些年,我们一起写过的“单例模式”

本文来自:“天天P图攻城狮”公众号(ttpic_dev) 题记 度娘上对设计模式(Design pattern)的定义是:“一套被反复使用、多数人知晓的、经过分...

3724
来自专栏我是攻城师

简述ElasticSearch里面复杂关系数据的存储方式

3607
来自专栏喔家ArchiSelf

一个函数的自白

我是——编程世界的函数,不是数学中的幂,指,对和三角函数等等,但是和f(x)又有着千丝万缕的关系。

785
来自专栏星流全栈

dva - React + Redux, but like elm

844
来自专栏進无尽的文章

设计模式| 结构型模式

其他同系列的文章还有: 面向对象编程中的六大原则 设计模式| 创建型模式 设计模式| 结构型模式 设计模式| 行为型模式 (上) 设计模式| 行为型模...

452
来自专栏.NET技术

面向对象基础

通过封装、继承、多态把程序的耦合度降低,用设计模式使程序更加的灵活,容易修改,并且易于复用。缩短开发周期,重用性和继承性高,降低了重复的工作量,但缺点是,程序的...

622
来自专栏java技术学习之道

百度"Java面试题"前200页都在这里了

842
来自专栏進无尽的文章

聊聊工程级别的组件化、插件化 以及 模块化

我们经常会听到组件化、插件化、模块化这三个概念,可是我们真的对这三个概念了解吗?明白它们三者之前的关系和区别吗?本文就我个人的理解做一下简单的总结,如有错误之处...

593
来自专栏程序员互动联盟

抓包工具Wireshark过滤规则实践第一篇

引子 现在从网上看到的一些wireshark过滤规则的介绍,都是比较老一点的,新版本的语法好像有所变化,所以在这里写一篇基于最新的1.12版本的wireshar...

3389
来自专栏知识分享

2-关于单片机通信数据传输(中断接收,大小端,IEEE754浮点型格式,共用体,空闲中断,环形队列)

1315

扫描关注云+社区