[.net 面向对象程序设计深入](26)实战设计模式——策略模式 Strategy (行为型)

1,策略模式定义

策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。

策略模式的组成:

—抽象策略角色: 策略类,通常由一个接口或者抽象类实现。 
—具体策略角色:包装了相关的算法和行为。 
—环境角色:持有一个策略类的引用,最终给客户端调用。 

2,策略模式适场景

(1)多个相关的类中,仅行为不同,即一个系统中需要在几个不同的算法中选择时。比如中出行中,我们选择交通方式火车、飞机、自行车、汽车等。

(2)一个算法的不同变体时。比如一个收取暖费的算法,不同的收费方式如按房屋面积、按供热焦耳量、按面积和热量混合法等 。

(3)不想暴露算法给使用者。比如,有一个复杂算法或算法中有相对应的数据结构不想让使用者知道。

(4)一个行为中有多个条件时。比如,有多个条件语句,而且实现比较复杂或比较长时,使用策略模式,除了结构清晰外,维护某一分支也比较方便。

3,策略模式优点

(1)抽象策略类和具体策略角色为环境类定义了一系列可以重用的算法或行为,并且继承有助于取出共用部分的算法。

(2)提供了可以替换继承关系的办法。可以创建一个环境类的子类,里面封装不同的行为,通过环境类来驱动策略。但这样也会导致环境类中的行为包含了具体实现,使用程序难以理解,难以维护。

(3)消除了复杂的IF..ELSE。含有许多复杂条件语句的代码可以使用策略模式来使逻辑更加清晰,易于维护。

(4)实了具有相同类型的多个行业的切换。让用户在多个策略中切换行为。

4,策略模式缺点

(1)需要事先知道所有策略类行为有何不同,才能让用户很好的选择。容易向使用者暴露策略中的各个行为。

(2)环境类和策略类之间产生通信开销。

(3)需要创建很多策略类。后面会说到享元模式,一定程度上减少类。

5,策略模式应用

(1)华山论剑

还是以熟悉的华山论剑为例,比赛方式(也就是三个具体策略类)有“比外功、比内功、比招式”,场景为“华山”(也就是场景类HuaShan),开始比赛了,主持人事先知道这几种比赛方式(也就是具体策略类),主持人(也就是具体使用者)让依次以这几种方式进行。

先看一下UML类图(在VS中使用类图,可以参考我前面的文章:在Visual Studio 2013/2015中设计UML类图

下面是具体代码:

抽象策略类 LunJian

public abstract class LunJian
{
public abstract void BiSai();
}

具体策略类 WaiGong NeiGong ZhaoShi

public class WaiGong : LunJian
{
public override void BiSai()
{
Console.WriteLine("外功比试开始了!");
}
}
public class NeiGong : LunJian
{
public override void BiSai()
{
Console.WriteLine("内功比试开始了!");
}
}
public class ZhaoShi : LunJian
{
public override void BiSai()
{
Console.WriteLine("招式比试开始了!");
}
}

场景类(也就是策略上下文 ) HuaShan

public class HuaShan
{
LunJian lunJian=null; public void SetLunJian(LunJian lunJian)
{
this.lunJian = lunJian;
} public void BiShi()
{
this.lunJian.BiSai();
}
}

使用者,就是控制台应用程序

class Program
{
static void Main(string[] args)
{
HuaShan huanShan = new HuaShan(); huanShan.SetLunJian(new WaiGong());
huanShan.BiShi(); huanShan.SetLunJian(new NeiGong());
huanShan.BiShi(); huanShan.SetLunJian(new ZhaoShi());
huanShan.BiShi(); Console.ReadLine();
}
}

依次给出三种比试方式策略,运行结果如下:

(2)华山论剑升级版

上面的示例比较简单,假如我们比试开始的时候,还需要点名两个比赛选手,这就需要在具体策略类的方法中增加参数。我们增加BiShi()方法参数,改进后代码如下:

抽象策略类 LunJian

public abstract class LunJian
{
public abstract void BiSai(string player1,string player2); }

具体策略类 WaiGong NeiGong ZhaoShi

public class WaiGong : LunJian
{
public override void BiSai(string player1,string player2)
{
Console.WriteLine("外功比试开始了!"+string.Format(" {0} 和 {1} 出场",player1,player2));
}
}
public class NeiGong : LunJian
{
public override void BiSai(string player1, string player2)
{
Console.WriteLine("内功比试开始了!" + string.Format(" {0} 和 {1} 出场", player1, player2));
}
}
public class ZhaoShi : LunJian
{
public override void BiSai(string player1, string player2)
{
Console.WriteLine("招式比试开始了!" + string.Format(" {0} 和 {1} 出场", player1, player2));
}
}

场景类(也就是策略上下文 ) HuaShan

public class HuaShan
{
LunJian lunJian=null; public void SetLunJian(LunJian lunJian)
{
this.lunJian = lunJian;
} public void BiShi(string player1,string player2)
{
this.lunJian.BiSai(player1,player2);
}
}

使用者,就是控制台应用程序

    class Program
{
static void Main(string[] args)
{
HuaShan huanShan = new HuaShan(); huanShan.SetLunJian(new WaiGong());
huanShan.BiShi("黄药师","欧阳锋"); huanShan.SetLunJian(new NeiGong());
huanShan.BiShi("洪七公","一灯大师"); huanShan.SetLunJian(new ZhaoShi());
huanShan.BiShi("欧阳锋","洪七公"); Console.ReadLine();
}
}

运行结果:

华山论剑的业务肯定比这个要复杂,上面的出场人不同,比赛方式不同,甚至还其他不同的规则出现。

如果我们不使用策略模式,而通过传统的if...else来写,不但要写很长的代码,还需要条件语句多次嵌套。

最主要的是代码的可读性较差,而且难以再解。

6,总结

(1)策略模式是一个比较容易理解和使用的设计模式,策略模式是对算法的封装,它把算法的责任和算法本身分割开,委派给不同的对象管理。策略模式通常把一个系列的算法封装到一系列的策略类里面,作为一个抽象策略类的子类。用一句话来说,就是“准备一组算法,并将每一个算法封装起来,使得它们可以互换”。
(2)在策略模式中,应当由客户端自己决定在什么情况下使用什么具体策略角色。
(3)策略模式仅仅封装算法,提供新算法插入到已有系统中,以及老算法从系统中“退休”的方便,策略模式并不决定在何时使用何种算法,算法的选择由客户端来决定。这在一定程度上提高了系统的灵活性,但是客户端需要理解所有具体策略类之间的区别,以便选择合适的算法,这也是策略模式的缺点之一,在一定程度上增加了客户端的使用难度。

7.实例源代码

https://github.com/yubinfeng/BlogExamples.git

==============================================================================================

返回目录

<如果对你有帮助,记得点一下推荐哦,如有有不明白或错误之处,请多交流>

<对本系列文章阅读有困难的朋友,请先看 《.net 面向对象编程基础》和 《.net 面向对象程序设计进阶》 >

<转载声明:技术需要共享精神,欢迎转载本博客中的文章,但请注明版权及URL>

.NET 技术交流群:467189533

==============================================================================================

[.net 面向对象程序设计深入](24)实战设计模式——策略模式(行为型)的更多相关文章

  1. [.net 面向对象程序设计深入](26)实战设计模式——策略模式 Strategy (行为型)

    [.net 面向对象程序设计深入](26)实战设计模式——策略模式 Strategy (行为型) 1,策略模式定义 策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模 ...

  2. 24种设计模式-策略模式(Strategy Pattern)

    一.优点: 1. 策略模式提供了管理相关的算法族的办法.策略类的等级结构定义了一个算法或行为族.恰当使用继承可以把公共的代码转移到父类里面,从而避免重复的代码. 2. 策略模式提供了可以替换继承关系的 ...

  3. 24种设计模式--策略模式【Strategy Pattern】

    刘备要到江东娶老婆了,走之前诸葛亮给赵云(伴郎)三个锦囊妙计,说是按天机拆开解决棘手问题,嘿,还别说,真是解决了大问题,搞到最后是周瑜赔了夫人有折兵呀,那咱们先看看这个场景是什么样子的. 先说这个场景 ...

  4. [.net 面向对象程序设计进阶] (24) 团队开发利器(三)使用SVN多分支并行开发(下)

    [.net 面向对象程序设计进阶] (24) 团队开发利器(三)使用SVN多分支并行开发(下) 本篇导读: 接上篇继续介绍SVN的高级功能,即使用分支并行开发.随着需求的不断变更,新功能的增加.特别是 ...

  5. PHP设计模式-策略模式 转

    策略模式(Strategy Pattern) 策略模式是对象的行为模式,用意是对一组算法的封装.动态的选择需要的算法并使用. 策略模式指的是程序中涉及决策控制的一种模式.策略模式功能非常强大,因为这个 ...

  6. 15. 星际争霸之php设计模式--策略模式

    题记==============================================================================本php设计模式专辑来源于博客(jymo ...

  7. 设计模式:Strategy 策略模式 -- 行为型

    设计模式 策略模式Strategy(对象行为型) 这是几年前写的文字(转载做的笔记更准确些),发觉还是废话多了点. 其实,核心就是5.结构中的UML图 5.1 和 5.2(新增).现在看这张图就觉得一 ...

  8. linkin大话设计模式--策略模式

    linkin大话设计模式--策略模式 Strategy [ˈstrætədʒi]  策略 策略模式用于封装系列的算法,这些算法通常被封装在一个称为Context的类中,客户端程序可以自由的选择任何一种 ...

  9. 面向对象设计模式--策略模式Strategy

    策略模式的UML类图(VS2013 C++版本): 策略模式的重点:每个策略对象封装一个算法,有多少个算法就有多少个对象.策略模式的意图是封装算法.要从“抽象不仅面对状态(字段.属性)还面对行为(算法 ...

随机推荐

  1. iOS NSTimer

    示例: //创建 scrollTimer =[NSTimer scheduledTimerWithTimeInterval:interval target:self selector:@selecto ...

  2. 文本切换器(TextSwitcher)的功能和用法

    TextSwitcher继承了ViewSwitcher,因此它具有与ViewSwitcher相同的特征:可以在切换View组件的同时使用动画效果.与ImageSwitcher相似的是,使用TextSw ...

  3. RAC时间同步的两种方法

    集群时间同步服务在集群中的两个 Oracle RAC 节点上执行以下集群时间同步服务配置.Oracle Clusterware 11g 第 2 版及更高版本要求在部署了 Oracle RAC 的集群的 ...

  4. 简单加解密算法 - vb.net

    Public Class Form1    Dim charAarray() As Char    '加密    Private Sub Btn_En_Click(sender As System.O ...

  5. 内功心法 -- java.util.ArrayList<E> (3)

    写在前面的话:读书破万卷,编码如有神--------------------------------------------------------------------下文主要对java.util ...

  6. VS Code C# 插件离线版 1.6.2

    VS Code C# 插件离线版,目前最新稳定版为:1.6.2 . 由于在扩展中下载C#插件总是缓慢,或者容易出现错误,特制作离线版本共享出来. 本离线版本为Windows版本,其他系统请在扩展中下载 ...

  7. 安装Oracle服务端后配置注册表与PL/SQL

    1.流程: 1.安装Oracle客户端(绿色版和安装版均可,建议安装在和Oracle服务端文件夹并行的路径下,例:E:\app\yginuo\product\11.2.0) 2.配置环境变量和注册表( ...

  8. 面向UI编程:ui.js 1.0 粗糙版本发布,分布式开发+容器化+组件化+配置化框架,从无到有的艰难创造

    时隔第一次被UI思路激励,到现在1.0的粗糙版本发布,掐指一算整整半年了.半年之间,有些细节不断推翻重做,再推翻再重做.时隔今日,终于能先出来个东西了,这个版本很粗糙,主体功能大概能实现了,但是还是有 ...

  9. Android仿微信朋友圈,全文收起功能,附源码

    在众多的社交类软件中,朋友圈是必不可少的,可以与好友.同学等分享自己的日常和有意思的事情,在开发社交类App时,朋友圈发表的内容你不可能让他全部显示,全部显示的话用户体验度会非常不好,这时就要用到全文 ...

  10. 性能秒杀log4net的NLogger日志组件(附测试代码与NLogger源码)

    NLogger特性: 一:不依赖于第三方插件和支持.net2.0 二:支持多线程高并发 三:读写双缓冲对列 四:自定义日志缓冲大小 五:支持即时触发刷盘机制 六:先按日期再按文件大小滚动Rolling ...