解读设计模式----策略模式(Strategy Pattern)
策略模式(Strategy Pattern)在外形上与状态模式很相似,但在意图上有些不同。其意图是使这些算法可以相互替换,并提供一种方法来选择最合适的算法。
在我应用OOP的设计过程演化(三)这篇文章里应用到了策略模式,在图书的租金计算上分多种情况,每一种不同类型的图书的租金是不一样的,而站在用户的角度来看,不同类型用户的租金收取又是不一样的,见下面分析:
计算机类图书:会员租借打5折,普通顾客租借打6折。
小说类图书:会员租借打6折,普通顾客租借打8折。
生活类图书:会员租借打9折,普通顾客租借打9折。
从上面分析可知,在租金计算这块是非常复杂的,由于有这样复杂的折扣算法,使得价格计算问题需要系统地解决。
书店经营一段时间后发现生活类的图书出租量很小,或许是因为租金的原因,很少有人来租借,于是老板决定降低租金,将生活类图书的租金按照计算机类的租金价格收取。这个时候怎么办?是不是已经有现存的计算机类图书租金计算策略,此时我们只需要把生活来图书的租金计算策略换为计算机类图书的租金计算策略便OK。通过这样的分析,策略模式(Strategy)正是解决这样的问题的模式,它的定义:"准备一组算法,并将每一个算法封装起来,使得它们可以互换。"
二、模式定义
定义:"准备一组算法,并将每一个算法封装起来,使得它们可以互换。"
三、模式意图
策略模式的用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。
四、模式UML图
五、模式参与者
根据上面UML,不难看出,在策略模式里主要有三种角色:环境角色、抽象策略角色和具体策略角色。
环境(Context)角色:持有一个抽象策略(Strategy)角色的引用。也叫上下文。
抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或一个抽象类来实现。
具体策略(ConcreteStrategy)角色:包装了相应的算法和行为。
六、简单示例
比如我们有这样一个需求,当我们的系统在记录操作日志的时候,客户要求提供多种日志记录策略,通过设置可以将日志记录到不同的地方(文本文件、XML文件以及数据库等),那么根据策略模式的定义,我们完全可以把不同的日志记录算法定义为一个独立的策略对象。
2{
3 /**//// <summary>
4 /// 抽象策略角色:这是一个抽象角色,通常由一个接口或抽象类实现。
5 /// 此角色给出所有的具体策略类所需的接口。
6 /// </summary>
7 public abstract class Strategy
8 {
9 public abstract void WriteLog();
10 }
11}
2/// 具体策略角色:包装了相关的算法或行为。
3/// </summary>
4public class DBStrategy:Strategy
5{
6 public override void WriteLog()
7 {
8 Console.WriteLine("日志被记录到数据库!");
9 }
10}
11
12/**//// <summary>
13/// 具体策略角色:包装了相关的算法或行为。
14/// </summary>
15public class TXTStrategy:Strategy
16{
17 public override void WriteLog()
18 {
19 Console.WriteLine("日志被记录到TXT文件!");
20 }
21}
22
23/**//// <summary>
24/// 具体策略角色:包装了相关的算法或行为。
25/// </summary>
26public class XMLStrategy:Strategy
27{
28 public override void WriteLog()
29 {
30 Console.WriteLine("日志被记录到XML文件!");
31 }
32}
2{
3 /**//// <summary>
4 /// 环境角色:持有一个Strategy类的引用
5 /// </summary>
6 public class Context
7 {
8 Strategy strategy;
9 /**//// <summary>
10 /// 初始化时传入具体的策略对象
11 /// </summary>
12 /// <param name="strategy"></param>
13 public Context(Strategy strategy)
14 {
15 this.strategy = strategy;
16 }
17
18 public void ContextStrategy()
19 {
20 strategy.WriteLog();
21 }
22
23 /**//// <summary>
24 /// 动态设置策略
25 /// </summary>
26 /// <param name="strategy"></param>
27 public void SetStrategy(Strategy strategy)
28 {
29 this.strategy = strategy;
30 }
31 }
32}
定义了一个抽象策略角色(Strategy),三种不同的日志记录策略(TXTStrategy、XMLStrategy和DBStrategy),也就是模式参与者中的具体策略角色,在环境角色里持有一抽象策略角色的引用,并通过构造器传入具体的策略对象初始化策略角色的引用,我们还定义了一动态设置策略的方法(SetStrategy),UML如下:
那么客户端就可以这样来使用这个策略:
2{
3 class Program
4 {
5 static void Main(string[] args)
6 {
7 //初始化时传入具体的策略对象
8 Context context = new Context(new XMLStrategy());
9 context.ContextStrategy();
10
11 //动态设置策略对象--改变策略
12 context.SetStrategy(new DBStrategy());
13 context.ContextStrategy();
14
15 context.SetStrategy(new TXTStrategy());
16 context.ContextStrategy();
17 }
18 }
19}
策略模式是一个提倡“针对接口编程”的模式,而使用接口的目的是为了统一标准或着说是制定一种强行的规定。此处抽象策略角色就担任了制定规定的角色,它制定了一种写日志(WriteLog方法)的规定。只要系统中需要记录日志就得使用这个规定(调用WriteLog方法),直接就使用他是不行的,就如去商场购物,要把商品带走不付费怎么行?
策略模式的使用是由用户发起的,根据用户的操作决定使用什么具体的策略角色。策略模式仅仅封装算法,提供新的算法加入到已有系统和算法间的相互替换,以及老算法从系统中“退休”的方便。策略模式并不决定在何时使用何种算法。因为使用何种算法决定权在用户,也就是说我们需要调用策略模式中定义好的算法方法之前,必须得选择一种具体的策略算法,上例中,客户端需要调用ContextStrategy方法,则调用前得为其设置一个具体的策略算法,如下:
2Context context = new Context(new XMLStrategy());
3context.ContextStrategy();
七、PetShop 4.0中的策略模式
PetShop 4.0的体系结构非常庞大,在订单处理上设计了两种处理策略,这里也是策略模式的一个应用,IOrderStrategy接口作为订单策略的高层抽象(抽象策略角色),实现不同订单处理的具体策略去实现它,UML如下:
示意性代码:
2{
3 public interface IOrderStrategy
4 {
5 void Insert(OrderInfo order);
6 }
7}
2{
3 public class OrderSynchronous:IOrderStrategy
4 {
5 private static readonly IOrder asynchOrder = QueueAccess.CreateOrder();
6
7 public void Insert(OrderInfo order)
8 {
9 asynchOrder.Send(order);
10 }
11 }
12}
13namespace PetShop.BLL
14{
15 public class OrderAsynchronous:IOrderStrategy
16 {
17 //
18 }
19}
从上面UML和代码就可以看出,订单策略接口下有两种实现,使用了抽象工厂模式来完成相应的订单策略对象的创建 。关于定单策略对象的创建详细可查阅ASP.NET中进行消息处理(MSMQ) 三 这篇文章,我在这里作了详细介绍。
八、模式的相关优点及缺点
定义了一系列的可供重用的算法和行为,继承有助于析取出这些算法中的公共功能。
Strategy模式可以提供相同行为的不同实现,客户可以根据不同的需求选择不同的Strategy。
客户必须了解不同的Strategy,一个客户要选择一个合适的Strategy就必须知道这些Strategy到底有何不同。
Strategy模式会增加对象的数目(具体的策略对象),可以将Strategy实现为可供各Context共享的无状态的对象来减少这一开销。任何其与的状态都由Context维护。
九、参考资料
张逸 《软件设计精要与模式》
GOF 《设计模式--可复用面向对象软件的基础》
MS开源项目PetShop 4.0
注:原创文章,转载请注明出处:http://beniao.cnblogs.com 或 http://www.cnblogs.com 作者:beniao
转载于:https://www.cnblogs.com/beniao/archive/2008/07/08/1236304.html
解读设计模式----策略模式(Strategy Pattern)相关推荐
- 关于设计模式——策略模式-Strategy Pattern
文章目录 1 策略模式 1.1 模拟鸭子 1.2 设计原则 1.3 整合行为 1.4 模拟鸭子代码的代码 1.5 动态设定行为 1.6 重新查看整体 1.7 继承和组合 1.8 总结 1.9 优劣期间 ...
- 设计模式——策略模式( Strategy Pattern )
写代码超过千行,自定义类10个以上,往往写着写着就觉的乱,最终决定抽空补习下设计模式方面的知识.本来AS3出了本关于设计模式的书的,国人也翻译了.我同事也早早买了一本,但前些天我借来看了几页,翻译的太 ...
- 设计模式-策略模式(Strategy Pattern)
Define a family of algorithms,encapsulate each one,and make them interchangeable(定义一组算法,将每个算法都封装起来,并 ...
- 设计模式(一):“穿越火线”中的“策略模式”(Strategy Pattern)
在前段时间呢陆陆续续的更新了一系列关于重构的文章.在重构我们既有的代码时,往往会用到设计模式.在之前重构系列的博客中,我们在重构时用到了"工厂模式"."策略模式" ...
- 8.6 GOF设计模式四: 策略模式… Strategy Pattern
策略模式- Strategy Pattern 在POS系统中,有时需要实行价格优惠, 该如何处理? 对普通客户或新客户报全价 对老客户统一折扣5% 对大客户统一折扣10% 注:课件 ...
- 二十四种设计模式:策略模式(Strategy Pattern)
策略模式(Strategy Pattern) 介绍 定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换.本模式使得算法的变化可独立于使用它的客户. 示例 有一个Message实体类,对它的操 ...
- 设计模式-策略模式(Strategy)-Java
设计模式-策略模式(Strategy)-Java 目录 文章目录 1.前言 2.示例案例-电影票打折方案 3.策略模式概述 3.1.策略模式定义 3.2.策略模式结构 3.3.策略模式结构图中角色 3 ...
- 李建忠设计模式——策略模式Strategy
目录 1.策略模式定义 1.动机 2.模式定义 3.结构 2.实现例子 1.问题描述 2.代码实现 3.要点总结 4.参考 1.策略模式定义 1.动机 软件构建过程中,某些对象使用的算法可能多种多样, ...
- 设计模式--策略模式(strategy)
1.策略模式(strategy ['strætədʒi]) 我的理解是:方案候选模式 (反正关键就是有很多的候选,哈哈) 看了很多例子,都是在说鸭子的,那个例子很好,在这里可以看 他们生产鸭子,我们就 ...
最新文章
- 操作系统学习2:操作系统的发展和概览
- scala学习手记25 - Curry化
- 如何在LOL中成功制造一颗飞弹?
- Django中间件2
- 深入理解 SAP Fiori Elements 工作原理系列之二:如何给 SAP Fiori Elements 应用添加自定义按钮
- 4国语言软件下载网站源码
- android 半边圆角背景,Android UI(一)Layout 背景局部Shape圆角设计
- easyexcel导入时读不到数据_easyexcel读取任意表格以及使用中的坑
- 《Spring源码深度解析》
- python爬取新浪博客_python爬取韩寒博客的实例
- Win8.1 ext-ms-win-ntuser-uicontext-ext-l1-1-0.dll等缺失
- mysql 纯真ip 导出dat_纯真IP数据库(qqwry.dat)转换成最新的IP数据库格式(ipwry.dat)
- Android——GSON解析JSON
- 股票术语之期货、期权
- js高级程序设计note
- 【Linux云计算架构:第三阶段-Linux高级运维架构】第26章——tcp三次握手四次挥手及在局域网中使用 awl伪装MAC地址进行多线程SYN攻击
- 时光机穿梭(管理修改)
- FlexPaper+SWFTools 实现仿百度文库及一些小问题
- Springboot(SpringBoot)重试机制retry
- 飞控学习常见典型问题集QA——无名创新(2022年4月15日)
热门文章
- 乘幂法、复化梯形以及二分法求特征值【相关例题python实现】
- 信号量CSemaphore的使用
- SpringMVC 配置文件实现(Tomcat)
- Golang笔记——json介绍
- 设计模式学习笔记——组合(Composite)模式
- 微信web开发者工具初次安装无法打开的几种解决办法
- windows10搜索网络计算机,教你如何关闭Win10搜索的网络搜索功能
- oracle数据库中的系统自带表情_oracle 系统自带几个常用函数
- html pdf文档的格式控制符,关于Unicode控制字符RLO,LRO,PDF 的坑
- java中math方法语句,下列有关Java中标准类Math的random()方法的说法中,正确的是。 - 上学吧学历考试...