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

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

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

一、概述

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 条评论
登录 后参与评论

相关文章

来自专栏C语言及其他语言

[每日一题]破解密码(1244)

向往如图灵一样破解密码吗?那么就请开始你的表演 题目描述 密码是我们生活中非常重要的东东,我们的那么一点不能说的秘密就全靠它了。哇哈哈. 接下来渊子要在密码之...

3349
来自专栏一个会写诗的程序员的博客

编译器之自举

**要阅读本文,不需要太高深的编译原理知识,甚至不需要编译相关的知识。但是本文也不是面向对电脑一无所知的读者的,你至少要知道:

821
来自专栏生信技能树

【生信菜鸟经】如何系统入门Perl

Perl是典型的脚本语言,短小精悍,非常容易上手,尤其适合处理文本,数据,以及系统管理。它在老一辈的生物信息学分析人员中非常流行,出于历史遗留原因大家肯定会或多...

3549
来自专栏顶级程序员

6 个新奇的编程方式,改变你对编码的认知

源 | Reddit 译 | OSC - 周其 我时不时会发现一种编程语言的不同用法它有时候会改变我对编程的看法啊。这篇文章中,我想分享一下让我惊讶的发...

2774
来自专栏Java学习网

60条面向对象设计原则

60条面向对象设计原则 你不必严格遵守这些原则,违背它们也不会被处以宗教刑罚。但你应当把这些原则看成警铃,若违背了其中的一条,那么警铃就会响起...

2376
来自专栏IT派

开放Python书籍:一本短小精悍的初学者入门指南

项目地址:https://github.com/joaoventura/full-speed-python

1390
来自专栏企鹅号快讯

给 iOS 开发者的 python 学习日记十二

写在前面 我们在昨天的学习笔记讨论了 Python 基本变数类型与资料结构可以应用的属性或方法,除了基本的资料结构以外,你是否还记得 Python 可以透过引入...

1885
来自专栏Java架构师进阶

编写高质量代码的思考

最近在看《代码大全》,可以说是一本软件开发的百科全书,特别厚,但是干货也很多。平时写代码,代码规范是一个最低的要求(很多老代码连最低要求都达不到),为什么要这样...

942
来自专栏点滴积累

shapeless官方指南翻译写在前面

目录 前言 Shapeless简介 The Type Astronaut's Guide to Shapeless简介 总结 一、前言        在我的20...

3587
来自专栏Python区块链

想到阿里巴巴从事Python吗?年薪300K不是梦!

作为Python工程师,进入大公司是开启职业新起点的关键,在阿里巴巴面试Python工程师的题目和经历,希望对广大Python工程师的求职者有一个帮助。

1896

扫码关注云+社区