设计模式之策略模式--Strategy Pattern

一、 策略(Strategy)模式

策略模式的用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。

假设现在要设计一个贩卖各类书籍的电子商务网站的购物车(Shopping Cat)系统。一个最简单的情况就是把所有货品的单价乘上数量,但是实际情况肯定比这要复杂。比如,本网站可能对所有的教材类图书实行每本一元的折扣;对连环画类图书提供每本7%的促销折扣,而对非教材类的计算机图书有3%的折扣;对其余的图书没有折扣。由于有这样复杂的折扣算法,使得价格计算问题需要系统地解决。

使用策略模式可以把行为和环境分割开来。环境类负责维持和查询行为类,各种算法则在具体策略类(ConcreteStrategy)中提供。由于算法和环境独立开来,算法的增减、修改都不会影响环境和客户端。当出现新的促销折扣或现有的折扣政策出现变化时,只需要实现新的策略类,并在客户端登记即可。策略模式相当于"可插入式(Pluggable)的算法"。

二、 策略模式的结构

策略模式是对算法的包装,是把使用算法的责任和算法本身分割开,委派给不同的对象管理。策略模式通常把一个系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。用一句话来说,就是:"准备一组算法,并将每一个算法封装起来,使得它们可以互换。"

策略又称做政策(Policy)模式【GOF95】。下面是一个示意性的策略模式结构图:

这个模式涉及到三个角色:

  • 环境(Context)角色:持有一个Strategy类的引用。
  • 抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
  • 具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。

三、 示意性源代码

 1 // Strategy pattern -- Structural example 
 2 using System;
 3 
 4 // "Strategy"
 5 abstract class Strategy
 6 {
 7  // Methods
 8  abstract public void AlgorithmInterface();
 9 }
10 
11 // "ConcreteStrategyA"
12 class ConcreteStrategyA : Strategy
13 {
14  // Methods
15  override public void AlgorithmInterface()
16  {
17  Console.WriteLine("Called ConcreteStrategyA.AlgorithmInterface()");
18  }
19 }
20 
21 // "ConcreteStrategyB"
22 class ConcreteStrategyB : Strategy
23 {
24  // Methods
25  override public void AlgorithmInterface()
26  {
27  Console.WriteLine("Called ConcreteStrategyB.AlgorithmInterface()");
28  }
29 }
30 
31 // "ConcreteStrategyC"
32 class ConcreteStrategyC : Strategy
33 {
34  // Methods
35  override public void AlgorithmInterface()
36  {
37  Console.WriteLine("Called ConcreteStrategyC.AlgorithmInterface()");
38  }
39 }
40 
41 // "Context"
42 class Context
43 {
44  // Fields
45  Strategy strategy;
46 
47  // Constructors
48  public Context( Strategy strategy )
49  {
50  this.strategy = strategy;
51  }
52 
53  // Methods
54  public void ContextInterface()
55  {
56  strategy.AlgorithmInterface();
57  }
58 }
59 
60 /// <summary>
61 /// Client test
62 /// </summary>
63 public class Client
64 {
65  public static void Main( string[] args )
66  {
67  // Three contexts following different strategies
68  Context c = new Context( new ConcreteStrategyA() );
69  c.ContextInterface();
70 
71  Context d = new Context( new ConcreteStrategyB() );
72  d.ContextInterface();
73 
74  Context e = new Context( new ConcreteStrategyC() );
75  e.ContextInterface();
76  }
77 }

 

四、 何时使用何种具体策略角色

在学习策略模式时,学员常问的一个问题是:为什么不能从策略模式中看出哪一个具体策略适用于哪一种情况呢?

答案非常简单,策略模式并不负责做这个决定。换言之,应当由客户端自己决定在什么情况下使用什么具体策略角色。策略模式仅仅封装算法,提供新算法插入到已有系统中,以及老算法从系统中"退休"的方便,策略模式并不决定在何时使用何种算法。

五、 一个实际应用策略模式的例子

下面的例子利用策略模式在排序对象中封装了不同的排序算法,这样以便允许客户端动态的替换排序策略(包括Quicksort、Shellsort和Mergesort)。

 1 // Strategy pattern -- Real World example 
 2 using System;
 3 using System.Collections;
 4 
 5 // "Strategy"
 6 abstract class SortStrategy
 7 {
 8  // Methods
 9  abstract public void Sort( ArrayList list );
10 }
11 
12 // "ConcreteStrategy"
13 class QuickSort : SortStrategy
14 {
15  // Methods
16  public override void Sort(ArrayList list )
17  {
18  list.Sort(); // Default is Quicksort
19  Console.WriteLine("QuickSorted list ");
20  }
21 }
22 
23 // "ConcreteStrategy"
24 class ShellSort : SortStrategy
25 {
26  // Methods
27  public override void Sort(ArrayList list )
28  {
29  //list.ShellSort();
30  Console.WriteLine("ShellSorted list ");
31  }
32 }
33 
34 // "ConcreteStrategy"
35 class MergeSort : SortStrategy
36 {
37  // Methods
38  public override void Sort( ArrayList list )
39  {
40  //list.MergeSort();
41  Console.WriteLine("MergeSorted list ");
42  }
43 }
44 
45 // "Context"
46 class SortedList
47 {
48  // Fields
49  private ArrayList list = new ArrayList();
50  private SortStrategy sortstrategy;
51 
52  // Constructors
53  public void SetSortStrategy( SortStrategy sortstrategy )
54  {
55  this.sortstrategy = sortstrategy;
56  }
57 
58  // Methods
59  public void Sort()
60  {
61  sortstrategy.Sort( list );
62  }
63 
64  public void Add( string name )
65  {
66  list.Add( name );
67  }
68 
69  public void Display()
70  {
71  foreach( string name in list )
72  Console.WriteLine( " " + name );
73  }
74 }
75 
76 /// <summary>
77 /// StrategyApp test
78 /// </summary>
79 public class StrategyApp
80 {
81  public static void Main( string[] args )
82  {
83  // Two contexts following different strategies
84  SortedList studentRecords = new SortedList( );
85  studentRecords.Add( "Samual" );
86  studentRecords.Add( "Jimmy" );
87  studentRecords.Add( "Sandra" );
88  studentRecords.Add( "Anna" );
89  studentRecords.Add( "Vivek" );
90 
91  studentRecords.SetSortStrategy( new QuickSort() );
92  studentRecords.Sort();
93  studentRecords.Display();
94  }
95 }

 

 六、 在什么情况下应当使用策略模式

在下面的情况下应当考虑使用策略模式:

1. 如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。

2. 一个系统需要动态地在几种算法中选择一种。那么这些算法可以包装到一个个的具体算法类里面,而这些具体算法类都是一个抽象算法类的子类。换言之,这些具体算法类均有统一的接口,由于多态性原则,客户端可以选择使用任何一个具体算法类,并只持有一个数据类型是抽象算法类的对象。

3. 一个系统的算法使用的数据不可以让客户端知道。策略模式可以避免让客户端涉及到不必要接触到的复杂的和只与算法有关的数据。

4. 如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。此时,使用策略模式,把这些行为转移到相应的具体策略类里面,就可以避免使用难以维护的多重条件选择语句,并体现面向对象设计的概念。

七、 策略模式的优点和缺点

策略模式有很多优点和缺点。它的优点有:

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

2. 策略模式提供了可以替换继承关系的办法。继承可以处理多种算法或行为。如果不是用策略模式,那么使用算法或行为的环境类就可能会有一些子类,每一个子类提供一个不同的算法或行为。但是,这样一来算法或行为的使用者就和算法或行为本身混在一起。决定使用哪一种算法或采取哪一种行为的逻辑就和算法或行为的逻辑混合在一起,从而不可能再独立演化。继承使得动态改变算法或行为变得不可能。

3. 使用策略模式可以避免使用多重条件转移语句。多重转移语句不易维护,它把采取哪一种算法或采取哪一种行为的逻辑与算法或行为的逻辑混合在一起,统统列在一个多重转移语句里面,比使用继承的办法还要原始和落后。

策略模式的缺点有:

1. 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。换言之,策略模式只适用于客户端知道所有的算法或行为的情况。

2. 策略模式造成很多的策略类。有时候可以通过把依赖于环境的状态保存到客户端里面,而将策略类设计成可共享的,这样策略类实例可以被不同客户端使用。换言之,可以使用享元模式来减少对象的数量。

八、 其它

策略模式与很多其它的模式都有着广泛的联系。Strategy很容易和Bridge模式相混淆。虽然它们结构很相似,但它们却是为解决不同的问题而设计的。Strategy模式注重于算法的封装,而Bridge模式注重于分离抽象和实现,为一个抽象体系提供不同的实现。Bridge模式与Strategy模式都很好的体现了"Favor composite over inheritance"的观点。

推荐大家读一读《IoC 容器和Dependency Injection 模式》,作者Martin Fowler。网上可以找到中文版的PDF文件。为策略模式的实施提供了一个非常好的方案。

转载于:https://www.cnblogs.com/tzh521241/archive/2012/07/21/StrategyPattern.html

设计模式--策略模式java例子 立即下载

相关推荐

HarmonyOS开发第一步:Dev Eco Studio4.0保姆级安装配置指南(含Node.js环境)

本文提供HarmonyOS开发环境搭建的保姆级教程,重点详解Dev Eco Studio 4.0的安装与配置,并攻克Node.js环境与Ohpm包管理器的关键设置难点。通过清晰的步骤指引,帮助开发者从零开始,高效完成开发环境部署,顺利迈出鸿蒙应用开发的第一步。

lake5的博客 569

如何用C#实践Policy based design

简介 http://www.codeproject.com/KB/cs/PolicyBasedCS.aspx 这篇是我在CodeProject的发文,在这篇文章中我用一个简单的范例示范如何在C#实践Policy based design的手法。 Policy的意思是方针,或

Cloud Hsu的专栏 3722

Splunk CVE-2018-11409认证绕过漏洞深度解析

Splunk作为主流企业级日志分析平台,其Web管理接口的认证机制直接关系到整个安全运营体系的可信边界。CVE-2018-11409本质上是REST API路由层会话校验缺失引发的未授权访问问题,根源在于`/en-US/splunkd/__raw/`路径绕过了splunkweb与splunkd之间的信任链验证,导致配置文件、用户哈希、App源码等敏感信息明文泄露。该漏洞凸显了Web接口权限模型设计失守的风险,尤其在默认配置未加固、HTTPS未启用、初始密码未修改的生产环境中危害急剧放大。结合vulfocus

weixin_30875157的博客 599

设计模式——策略模式(附代码示例)

一. 传统方式 以统计不同鸭子信息为例 1. 传统方式解决 抽象一个Duck类,不同鸭子继承Duck,如果有相同行为就默认继承,有不同行为就重写 类图 代码实现 Duck抽象类 public abstract class Duck { public Duck() { } public abstract void display(); public void quack(){ System...

枫陵的博客 2511

网络抓包实战:如何捕获与解析802.1Q VLAN标签报文

在网络通信中,数据包是信息传输的基本单元,而VLAN(虚拟局域网)技术通过在数据链路层插入802.1Q标签,实现了网络流量的逻辑隔离与高效管理。其核心原理是在标准以太网帧头中嵌入4字节的VLAN标识,使交换机能够根据VID(VLAN ID)进行精准转发。掌握VLAN报文的捕获与解析技术,对于网络故障排查、安全审计和性能优化具有重要价值,尤其在需要验证网络隔离策略或诊断Trunk链路异常时。本文聚焦于使用Wireshark工具,结合端口镜像等实操方法,详细演示如何抓取并解读携带802.1Q标签的原始报文,帮助

weixin_33417488的博客 383

(南京观海微电子)——GH700X调试指南--SPI 接口+LVDS-测试盒使用方法

1表示OTP完成后,读取烧录值是否一致来判断是否烧录成功,2表示同时检测VCOM是否一致以及烧录次数是否增加,3表示不做任何检测,由用于自行在程序中判断。[格式]:SetFindVcomEn (<开启或关闭>),ON表示开启VCOM搜寻,默认是开启的,只要使能OTP烧录,按OTP按键则进行VCOM查询;[功能]:OTP完成检测类别,用于设置OTP完成后检测OTP次数还是OTP值来判断OTP是否成功。[功能]:用于设置VCOM查询使能,比如需要烧全代码而不需要对VCOM查询时,可以禁止VCOM查询。

m0_75095200的博客 1666

设计模式(三):策略模式(Strategy)案例分享

策略模式非常实用,可以替换很多if else,比如上面代码如果要用if else 实现那么可能要写3个判断执行对应方法使用策略模式可以提高代码可读性,方便后面随着业务扩展,代码不断调整//spring会将实现同一策略接口的所有策略实现类放到map @Autowired private Map < String , FolderDragStrategy > folderDragStrategyMap;} } }

码农阿福的博客 702

CentOS 7 常用命令大全

CentOS中Linux命令

m0_63075763的博客 2018

Java设计模式 Design Pattern:策略模式 Strategy Pattern

意图 Define a family of algorithms, encapsulate each one, and make them interchangeable. 定义一组算法,封装每一个算法,并使他们可以互换 Strategy lets the algorithm vary independently from clients that use it. 策略使得算法可以

OYJJ的专栏 1719

用AI生成React/Vue页面?实测Locofy等5款工具,教你选最适合的

本文深度评测了2024年五大AI生成前端页面工具,包括Locofy、Builder.io等,从代码质量、可视化编辑器成本到企业级落地方案进行全面分析。通过实测数据和实战案例,揭示如何利用AI生成技术高效创建React/Vue页面,提升开发效率并优化性能。

m5n6o7的博客 606

Halcon算子知识:optical_flow_mg

光流(Optical Flow)是一种研究图像对齐的算法,一般包括两大类:稀疏光流和稠密光流。稀疏光流就是研究图像中稀疏点的光流,这些点一般是角点;稠密光流则是研究图像中所有点的偏移量。以下介绍halcon的基本光流算子optical_flow_mg的原理方法。该算子计算两个图片的光流法。 二、算子说明 optical_flow_mg(ImageT1, ImageT2 : VectorField : Algorithm, SmoothingSigma, Integration

gongdiwudu的专栏 1万+

设计模式:策略模式(Strategy Design Pattern)

个人觉得学习设计模式的话,还是应该注重各种设计模式的应用场景,23种设计模式真的挺多的,要靠死记硬背的话还是没那么容易记住。所以我建议可以在自己实际编码时,套用上各种设计模式。 策略模式是一个很好的例子,如果需要用到大量的if~else判断的话,就可以用到策略模式 我们使用的app大多都有分享的功能,我们可以选择分享到不同的地方,比如微博、微信、QQ等等,虽然是同一个内容,但是分享到不同的平台就会有不同的处理方式,比如要跳转到不同的app或者直接复制链接等等。如果让你来实现这个功能,你会如何实现呢? 用了

weixin_45251189的博客 3712

STM32(HAL库)驱动HC-SR04测距模块

本文介绍通过STM32F103C8T6单片机对HC-SR04测距模块进行驱动,并且通过串口对数据进行打印。

weixin_44597885的博客 2204

深入浅出设计模式(Design Pattern)----策略模式(Strategy Pattern)

深入浅出设计模式(Design Pattern)----策略模式(Strategy Pattern) 这是设计模式开篇,我觉得策略模式真的对我来说是一种醍醐灌顶的感觉.让我感觉:哇,真的诶,用这种设计模式真的可以方便很多,代码的层次结构更清晰.下面就让我们开始吧.策略模式:策略模式定义了算法族,分别将其封装起来,让他们之间可以相互转换,这个模式使得算法的变化独立于使用算法的客体. 但是严谨的定义通常是难以理解的,接下来我们通过一个故事,来深刻理解这种设计模式的使用场景和强大之处吧(以下例子来自Head

阿伟のBlog 733

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

[图书小结] 深入浅出设计模式:策略模式 The Strategy Pattern

[图书小结] 深入浅出设计模式:策略模式 The Strategy Pattern问题背景继承 (Inheritance) 的局限性 -- The Limitations of Inheritance改用接口 (Interface) 如何 -- How about an Interface?思考分析Design Principle 设计原则1. Encapsulate what varies 抽取出并封装会发生变化的那些2. Program to an interface, not an implement

dev_的博客 192

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

23种设计模式之策略模式(Strategy Pattern)

本篇文章将23种设计模式中的策略模式,此篇文章为一天学习一个设计模式系列文章,后面会分享其他模式知识。

小威的博客 1万+

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

设计模式之策略模式(Strategy Design Pattern)

模板模式,是11种行为型模式之一。在 GoF 的《设计模式》一书中,它是这样定义的:Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.翻译成中文就是:定义一系列算法(策略),封装每一个算法(策略),并使它们可以互换。使算法(策略)可以独立于使用它的客

xjj1314的专栏 428

设计模式-策略模式-Strategy Pattern

策略模式(Strategy Pattern)是一种行为型设计模式,它定义了一系列的算法,并将每一个算法封装起来,使它们可以互换使用,算法的变化不会影响使用算法的用户。策略模式的优点包括算法的封装和切换的灵活性,以及算法可独立于使用它的客户端变化。:如果算法的实现非常复杂,或者算法可能会随着时间而变化,策略模式可以帮助管理这种复杂性,使得算法的变化不会影响到使用算法的代码。:在需要根据不同条件动态切换算法的场景中,策略模式可以提供灵活的算法切换机制,例如,根据输入数据的特性选择不同的算法。

wesigj的博客 1456

23种设计模式——策略模式 (Strategy Pattern)​详解

本文介绍了23种经典设计模式之——策略模式 (Strategy Pattern)​的说明及使用

Meteors.的博客 837

设计模式-19策略模式Strategy Pattern

策略模式是一种行为设计模式,通过定义一系列可互换的算法并将其封装,使算法能独立于使用它的客户端而变化。该模式适用于需要动态切换不同算法或行为的场景,可避免大量条件判断语句。其核心结构包括策略接口、具体策略类和使用策略的上下文类。实现时,先定义策略接口,然后创建具体策略类实现接口方法,最后通过上下文类动态设置和切换策略。示例展示了支付系统中的多种支付策略(信用卡、PayPal、银行转账)的灵活切换,体现了策略模式的可扩展性和解耦优势。 (149字)

d3y1`5 81_09 1088

C++设计模式——策略模式(Strategy Pattern)

C++设计模式——策略模式(Strategy Pattern) 微信公众号:幼儿园的学霸 目录 文章目录C++设计模式——策略模式(Strategy Pattern)目录定义实现示例传统的策略模式实现使用函数指针实现策略模式工厂模式和策略模式对比总结参考资料 定义 Define a family of algorithms,encapsulate each one,and make them interchangeable. 定义一组算法,将每个算法都封装起来,并且使它们之间可以互换 策略模式是指定

leonardohaig的博客 4773

设计模式中的策略模式(Strategy Pattern)

在软件开发中,经常遇到多个算法或行为可以互换的情况,例如不同的支付方式、排序算法、日志记录方式等。如果使用 `if-else` 或 `switch-case` 选择不同的策略,代码将变得复杂且难以维护。策略模式(Strategy Pattern) 提供了一种定义一组算法,并在运行时选择合适的算法的方法,从而使代码更加灵活、可扩展、符合开闭原则(OCP)。本文将详细介绍策略模式的概念、应用场景,并通过 Python 代码示例展示其实现方式。

1782

【设计模式】策略模式(Strategy Pattern)详解

策略模式(Strategy Pattern)是一种行为型设计模式,

qq_59344127的博客 1839

C#设计模式之策略模式(Strategy Pattern)

概述:        策略模式是对算法的包装,是把使用算法的责任和算法本身分割开来,委派给不同的对象管理。策略模式通常把一个系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。用一句话来说,就是:“准备一组算法,并将每一个算法封装起来,使得它们可以互换”。下面就以一个示意性的实现讲解策略模式实例的结构。 这个模式涉及到三个角色: 环境(Context)角色:持有一个St

donnie88888888的专栏 4065

设计模式-策略模式(Strategy Pattern)

策略模式 定义 定义了一组算法,将每个算法都封装起来,并且使它们之间可以互换,且算法的变化不会影响使用算法的客户。它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。 类型 行为型。 角色 抽象策略(Strategy):定义了一个公共接口,各种不同的算法以不同的方式实现这个接口,环境角色使用这个接口调用不同的算法,一般使用接口或抽象类实现。 具体策略...

kaven 1653
上一篇: 设计模式之简单工厂模式--Simple Factory Pattern
下一篇: ASP.NET MVC 3新特性
datuo2821
博客等级 码龄11年 0粉丝 0原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值