策略模式可能是在工作中使用最多的,也是在面试中最常提到的,代码重构和优化的必备!
小编之前也是一直说,其实没有真正的实战;最近有了机会实战了一下,来分享一下使用心得和在企业级的使用!
策略模式,英文全称是 Strategy Design Pattern。在 GoF 的《设计模式》一书中,它是这样定义的:
定义一族算法类,将每个
算法分别封装起来,让它们可以互相替换。策略模式可以使算法的变化独立于使用它们的客户端(这里的客户端代指使用算法的代码)。
其实以上三部分用白话文来解释就是:
需要一个接口和策略进行规范和约束接口和方法,这时需要一些具体的实现算法类去继承或者实现刚刚的接口和策略,最后通过一个环境或者上下文,也可以叫做工厂根据类型进行调用具体的算法!
具体场景一般为:
优点:
缺点:
今天小编根据春夏秋冬四季需要做不同的事情来演示一下策略模式的使用方案;
需求是:
如果是春天,就要去放风筝
如果是夏天,就要去游泳
如果是秋天,就要去看枫叶
如果是冬天,就要去打雪仗
没有使用策略模式的话,肯定就是
if-if else进行实现!
下面就带大家体会一下具体使用哈!!
/**
* 四季策略
* @author wangzhenjun
* @date 2022/12/1 9:30
*/
public interface SeasonsStrategy {
/**
* 根据季节去执行不同的方案
* @param seasons
* @return
*/
String execute(String seasons);
}
/**
* 春季具体实现
* @author wangzhenjun
* @date 2022/12/1 9:34
*/
// 指定容器的名称,不指定默认为类名称首字母小写
@Component("spring")
public class SpringStrategy implements SeasonsStrategy{
@Override
public String execute(String seasons) {
return seasons + "来了!我们一起去放风筝吧!";
}
}
/**
* 夏季具体实现
* @author wangzhenjun
* @date 2022/12/1 9:34
*/
// 指定容器的名称,不指定默认为类名称首字母小写
@Component("summer")
public class SummerStrategy implements SeasonsStrategy{
@Override
public String execute(String seasons) {
return seasons + "来了!我们一起去游泳吧!";
}
}
/**
* 秋季具体实现
* @author wangzhenjun
* @date 2022/12/1 9:34
*/
// 指定容器的名称,不指定默认为类名称首字母小写
@Component("autumn")
public class AutumnStrategy implements SeasonsStrategy{
@Override
public String execute(String seasons) {
return seasons + "来了!我们一起去放看枫叶吧!";
}
}
/**
* 冬季具体实现
* @author wangzhenjun
* @date 2022/12/1 9:34
*/
// 指定容器的名称,不指定默认为类名称首字母小写
@Component("winter")
public class WinterStrategy implements SeasonsStrategy{
@Override
public String execute(String seasons) {
return seasons + "来了!我们一起去打雪仗吧!";
}
}
private Map<String, SeasonsStrategy> seasonsMap;这是最重要的,很多时候我们都知道怎么进行策略和实现怎么写,不知道怎么统一去放进去,来进行调用,可以自己放在map中。当然spring已经给我们组装好了,只要按需调用即可!
核心:
Spring会自动将Strategy接口的实现类注入到这个Map中,key为bean id,value值则为对应的策略实现类!
/**
* 环境或者上下文类,用于统一执行具体策略
* @author wangzhenjun
* @date 2022/12/1 9:56
*/
@Component
public class SeasonsFactory {
/**
* Spring会自动将Strategy接口的实现类注入到这个Map中,key为bean id,value值则为对应的策略实现类
*/
@Autowired
private Map<String, SeasonsStrategy> seasonsMap;
/**
* 处理四季统一入口方法
* @param seasons
* @param beanName
* @return
*/
public String handle(String seasons,String beanName){
// 根据bean的名称获取对应的算法处理类
SeasonsStrategy seasonsStrategy = seasonsMap.get(beanName);
String execute = seasonsStrategy.execute(seasons);
return execute;
}
}
@Slf4j
@RestController
@RequestMapping("/test")
public class TestController {
@Autowired
private SeasonsFactory seasonsFactory;
@GetMapping("/strategyTest/{seasons}/{beanName}")
public Result strategyTest(@PathVariable("seasons") String seasons,@PathVariable("beanName") String beanName){
String handle = seasonsFactory.handle(seasons, beanName);
return Result.success(handle);
}
}
http://localhost:8087/test/strategyTest/春天/spring

http://localhost:8087/test/strategyTest/夏天/summer

在策略模式中定义了一系列算法,将每一个算法封装起来,并让它们可以相互替换,互不影响。
策略模式得益于按照开闭原则进行设计,各个具体算法按照单一职责原则设计; 提高了代码的复用性,对客户隐藏具体策略 (算法) 的实现细节,彼此完全独立,扩展其余不受影响;避免if-else 或 switch 分支语句判断;其缺点在于客户端必须知道所有的策略类,增加了系统中类的个数。
在日常开发一般用于消除多重判断,有时候不要为了用设计模式而用设计模式,一定要结合业务场景,过度设计也是很致命的!!
如果对你有帮助,还请不要吝啬您的发财小手,你的一键三连是我写作的动力,谢谢大家哈!!

我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po