`

Strategy 模式

阅读更多

Strategy 模式

文章出自:http://blog.csdn.net/wy818/archive/2009/04/09/4056149.aspx

优先考虑使用策略模式,而不是具体继承 Rod

产生的原因: 属于对象的行为模式。处理多于一个算法时候,把算法和使用算法的客户端分开(把行为和环境分割开),从而方便的选择其中一个算法。

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

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

程序架构:一个客户类,一个抽象策略类(接口),若干个具体策略类。由客户类决定选择那一个具体类。

定义一系列的算法,把他们一个个封装起来,并且使它们可相互替换。Strategy模式使算法可独立于使用它的客户而变化。

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

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

 

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

·  环境(Context)角色:持有一个Strategy类的引用。

·  抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。

·  具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。

Strategy模式以下列几条原则为基础:

1 每个对象都是一个具有职责的个体。

2 这些职责不同的具体实现是通过多态的使用来完成的。

3 概念上相同的算法具有多个不同的实现,需要进行管理

通过以下步骤,开发人员可以很容易地在软件中实现策略模型:

      1)对策略对象定义一个公共接口。

      2)编写策略类,该类实现了上面的公共接口。

       3)策略对象的类中保存一个对策略对象的引用。

       4)略对象的类中,实现对策略对象的setget方法。

:

首先,我们建立一个抽象类RepTempRule 定义一些公用变量和方法:

public abstract class RepTempRule{

protected String oldString="";
public void setOldString(String oldString){
  
this.oldString=oldString;
}

protected String newString="";
public String getNewString(){
  
return newString;
}



public abstract void replace() throws Exception;


}

RepTempRule 有一个抽象方法abstract需要继承明确,这个replace里其实是替代的具体方法.
我们现在有两个字符替代方案
,
1.
将文本中aaa替代成
bbb;
2.
将文本中aaa替代成
ccc;

对应的类分别是RepTempRuleOne RepTempRuleTwo

public class RepTempRuleOne extends RepTempRule{


public void replace() throws Exception{

  //replaceFirstjdk1.4新特性

  
newString=oldString.replaceFirst("aaa", "bbbb")
  
System.out.println("this is replace one");
  

}


}

 

public class RepTempRuleTwo extends RepTempRule{


public void replace() throws Exception{

  
newString=oldString.replaceFirst("aaa", "ccc")
  
System.out.println("this is replace Two");
  

}


}

第二步:我们要建立一个算法解决类,用来提供客户端可以自由选择算法。

public class RepTempRuleSolve {

  private RepTempRule strategy;

  public RepTempRuleSolve(RepTempRule rule){
    
this.strategy=rule;
  }

  public String getNewContext(Site site,String oldString) {
    
return strategy.replace(site,oldString);
  }

  public void changeAlgorithm(RepTempRule newAlgorithm) {
    
strategy = newAlgorithm;
  }

}

调用如下:

public class test{

......

  public void testReplace(){

  //使用第一套替代方案
  RepTempRuleSolve solver=new RepTempRuleSolve(new RepTempRuleOne());
  solver.getNewContext(site,context);

  //使用第二套

  solver=new RepTempRuleSolve(new RepTempRuleTwo());
  solver.getNewContext(site,context);

  }

.....

}

我们达到了在运行期间,可以自由切换算法的目的。

实际整个Strategy的核心部分就是抽象类的使用,使用Strategy模式可以在用户需要变化时,修改量很少,而且快速.

StrategyFactory有一定的类似,Strategy相对简单容易理解,并且可以在运行时刻自由切换。Factory重点是用来创建对象。

Strategy适合下列场合:

1.以不同的格式保存文件;

2.以不同的算法压缩文件;

3.以不同的算法截获图象;

4.以不同的格式输出同样数据的图形,比如曲线 或框图bar

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

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

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

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

策略模式的缺点有:

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

2. 策略模式造成很多的策略类。有时候可以通过把依赖于环境的状态保存到客户端里面,

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

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

分享到:
评论

相关推荐

    动态加载概述与原理.docx

    动态加载概述与原理.docx

    LOL_params_0900000.pt

    LOL_params_0900000.pt

    分群用户详情_7_2024-09-06 09_49_58.xlsx

    分群用户详情_7_2024-09-06 09_49_58

    动态加载的高级主题:懒加载与按需加载.docx

    动态加载的高级主题:懒加载与按需加载.docx

    【超强组合】基于VMD-开普勒优化算法KOA-Transformer-LSTM的光伏预测算研究Matlab实现.rar

    1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。 替换数据可以直接使用,注释清楚,适合新手

    Minecraft 1.20.1 Paper Plugin-基于Towny Flagwar 为其实现中立国家

    为Towny Flagwar实现中立国家 /nasetnu 设置自己的国家为中立(仅king可用)

    resnet模型-基于图像分类算法对度假胜地识别-不含数据集图片-含逐行注释和说明文档.zip

    本代码是基于python pytorch环境安装的。 下载本代码后,有个环境安装的requirement.txt文本 首先是代码的整体介绍 总共是3个py文件,十分的简便 本代码是不含数据集图片的,下载本代码后需要自行搜集图片放到对应的文件夹下即可 需要我们往每个文件夹下搜集来图片放到对应文件夹下,每个对应的文件夹里面也有一张提示图,提示图片放的位置 然后我们需要将搜集来的图片,直接放到对应的文件夹下,就可以对代码进行训练了。 运行01生成txt.py,是将数据集文件夹下的图片路径和对应的标签生成txt格式,划分了训练集和验证集 运行02CNN训练数据集.py,会自动读取txt文本内的内容进行训练,这里是适配了数据集的分类文件夹个数,即使增加了分类文件夹,也不需要修改代码即可训练 训练过程中会有训练进度条,可以查看大概训练的时长,每个epoch训练完后会显示准确率和损失值 训练结束后,会保存log日志,记录每个epoch的准确率和损失值 最后训练的模型会保存在本地名称为model.ckpt 运行03pyqt界面.py,就可以实现自己训练好的模型去识别图片了

    基于Java的订餐系统设计与实现:涵盖系统架构、前端交互与数据库管理

    内容概要:本文详细介绍了一款基于Java的订餐系统的设计与实现。文章首先介绍了互联网时代背景下,订餐系统作为一种新型生活方式的便捷性与必要性。接着阐述了系统的设计背景、目的及其所采用的技术框架(如JSP、MySQL、MyEclipse)。系统分为前台和后台两大部分,前台主要负责用户的界面展示和互动,包括食品展示、查询、购物车等功能;后台则是管理员进行餐品管理和用户信息维护的平台。文中还详细解析了各主要功能模块的设计思路和技术实现细节,以及数据库表结构的设计。 适合人群:具备一定的Java开发基础,对Web应用开发有兴趣的初学者或工程师。 使用场景及目标:用于学习基于B/S架构的订餐系统的开发全过程,理解前后端分离、JSP动态页面生成、MySQL数据库操作等核心技术的应用。适合希望深入了解餐饮管理系统内部运作机制的学生或从业者。 其他说明:此系统设计符合现代互联网发展趋势,通过引入JSP、JavaScript、MySQL等主流技术,旨在提高餐饮行业的管理效率和服务水平,增强用户体验。此外,本项目也包含了系统测试的内容,确保各项功能的正常运转。

    【java毕业设计】家用电器销售网站源码(ssm+jsp+mysql+说明文档+LW).zip

    功能说明: 管理员:个人中心、用户管理、商品分类管理、品牌管理、商品信息管理、订单评价管理、留言板管理、系统管理、订单管理。用户:个人中心、订单评价管理、我的收藏管理、订单管理。前台首页:首页、商品信息、商品资讯、留言反馈、我的、跳转到后台、购物车等功能的家用电器销售网站。 环境说明: 开发语言:java 框架:ssm jdk版本:jdk1.8 数据库:mysql 5.7+ 数据库工具:Navicat11+ 管理工具:maven 开发工具:idea/eclipse 部署容器:tomcat7+

    联想电脑的bios设置

    联想电脑的bios设置、图文都有

    基于springboot+vue+redis+mysql实现的大学生宿舍管理系统【源码+数据库】

    技术:ssm+mysql+redis vue+element 功能:宿舍管理、学生管理、班级管理、宿舍楼管理、维修记录、晚归记录、请假记录、用户管理、角色管理、菜单管理、日志管理

    【超强组合】基于VMD-飞蛾扑火优化算法MFO-Transformer-GRU的光伏预测算研究Matlab实现.rar

    1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。 替换数据可以直接使用,注释清楚,适合新手

    跨浏览器兼容性测试.docx

    跨浏览器兼容性测试.docx

    编译供c语言使用的Vosk库,可以直接使用省去编译的麻烦过程

    Vosk是一个开源的语音识别工具,支持中英文及多种语言,具备离线识别能力,且不依赖互联网。优势 Vosk 是一个离线开源语音识别工具包,它的优点在于: 轻量:Vosk 提供轻量级的模型(小于 50MB 大小),可以用于低功耗平台(例如 Android、树莓派之类) 多编程语言、多平台支持:Python、Java、Node.js、C#、C++、Rust、Go 等 多语种支持:支持二十多种语言的识别(包括中文) 实时性:实时性语音识别场景下,vosk 的延迟非常低 简单来讲,你电脑中有 Python 环境,再下载一个 50 MB 的模型,就可以用 Vosk 实现一个正确率还可以接受的语言识别相关的项目。而像 Whisper 虽然识别效果好,但是对硬件要求很高,同时部署起来麻烦(例如需要配置 CUDA 环境),另外也不是很适用于实时性场景。 此包为编译好的c调用的运行库,有需要的可以直接下载使用。

    影视源码自动对接资源站开源源码

    影视源码自动对接资源站开源源码

    【超强组合】基于VMD-多元宇宙优化算法MVO-Transformer-GRU的光伏预测算研究Matlab实现.rar

    1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。 替换数据可以直接使用,注释清楚,适合新手

    大学生社团管理系统 SSM毕业设计 附带论文.zip

    大学生社团管理系统 SSM毕业设计 附带论文 启动教程:https://www.bilibili.com/video/BV1GK1iYyE2B

    网络安全 - 图片文件黑客攻击

    网络安全 - 图片文件黑客攻击

    【活字格插件】文件复制

    服务器可运行。实现文件复制。

    【超强组合】基于VMD-淘金优化算法GRO-Transformer-GRU的光伏预测算研究Matlab实现.rar

    1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。 替换数据可以直接使用,注释清楚,适合新手

Global site tag (gtag.js) - Google Analytics