一、基本概念

既然你已经接触到了设计模式,那你大概率你写过类似这样的代码:根据不同的选择条件(如排序、搜索或路由)执行不同的代码逻辑。通常的解决方案是使用if-elseswitch语句,但这些条件判断有一个最大的问题是不够灵活,难以扩展(也就是违背了开闭原则)。
策略模式是一种行为型设计模式,策略模式提供了一种更优雅的解决方案,你可以定义一系列算法,然后将每个算法封装成独立类,使得无需修改核心逻辑就能在不同算法(代码逻辑)间自由切换。

The algorithm can change without changing the context that uses it.
相比于将所有代码逻辑硬编码在一个庞大的类中,更好的方案是编写不同的策略(算法),然后将它们灵活的插入上下文。

案例类比:去公司的交通方式。
假设你是一只每天可以睡到10点才去上班的哈基米,有以下交通方式可选:
• 共享单车:环保但费力
• 公交:便宜但不够灵活(可能还要步行一段儿)
• 嘀嘀打车:唯一的缺点就是贵
这些都是交通策略(可以看做一个个独立的算法)。根据时间、预算或心情,你可以选择不同策略。决策逻辑不变,只是切换策略而已,这和策略模式在代码中的使用方式比较相似。

2. 使用案例

2.1 情景引入

扩展刚才的案例,假设你跳槽了,换了一家公司,但你对公司所在位置不熟悉,正在学习软件开发的你打算开发一个导航应用,支持多种出行方式的路线规划。

  • 步行路线
  • 自行车路线
  • 公交路线
  • 驾车路线

在v1版本,你只实现了你最常用的公交路线。随后陆续添加了步行、自行车和驾车等功能。最终你完成了这样的路线计算方法:

if (mode.equals("bus")) {// 驾车路线代码逻辑
} else if (mode.equals("walk")) {// 步行路线代码逻辑
} else if (mode.equals("bike")) {// 自行车路线代码逻辑
} else { // 其他模式... 
}

随着路线规划方式的增加,if-else变得越来越多。如果你打算和朋友协作完成这个项目,你会发现代码修改不方便,甚至合并时还会产生冲突。

2.2 解决方案——策略模式

2.2.1核心概念
  • 策略接口:声明算法规约(如execute()方法)。
  • 具体策略:实现策略接口的不同算法。
  • 上下文:持有策略引用并将行为委托给这个引用。
  • 客户端:选择使用哪种策略并注入上下文。
2.2.2 Java实现

第一步:定义策略接口

public interface RouteStrategy {String execute();
}

第二步:实现具体策略

// 驾车路线策略
public class DriveStrategy implements RouteStrategy {@Overridepublic String execute() {return "Bike route";}
}// 步行路线策略
public class WalkStrategy implements RouteStrategy {@Overridepublic String execute() {return "Walk route";}
}// 公共交通路线策略
public class MassTransitStrategy implements RouteStrategy {@Overridepublic String execute() {return "MassTransit route";}
}

第三步:上下文类

public class Context {// 注入策略接口(持有引用)private RouteStrategy routeStrategy;public void setRouteStrategy(RouteStrategy routeStrategy) {this.routeStrategy = routeStrategy;}// 行为委托给这个引用public String getRoute() {if (routeStrategy == null) {throw new IllegalStateException("未设置策略!");}return routeStrategy.execute();}
}

第四步:客户端选择策略

public class Client {public static void main(String[] args) {Context context = new Context();context.setRouteStrategy(new DriveStrategy());System.out.println("驾车路线: " + context.getRoute());context.setRouteStrategy(new WalkStrategy());System.out.println("步行路线: " + context.getRoute());context.setRouteStrategy(new MassTransitStrategy());System.out.println("公共交通路线: " + context.getRoute());}
}

执行结果
在这里插入图片描述

3. 策略模式 vs 状态模式

策略模式(Strategy) 和 状态模式(State) 看起来很相似:二者都通过委托实现,替换一个实现了相同接口的不同对象。但它们在设计意图、控制流和动机上存在本质区别。

策略模式状态模式
设计意图核心是让客户端(外部调用者)选择具体算法,关注的是可独立变化的行为。例如上述案例中选择不同路径计算逻辑。用于表示一个对象在不同时间点的不同状态或条件,其状态转换由对象自身的内在逻辑决定
控制流客户端显式决定使用哪种策略(如通过 setStrategy(…) 动态切换)状态转换由上下文对象内部驱动,行为随状态自动改变,客户端通常无需感知具体状态。
感知与状态转换​​各策略对象之间​​相互独立​​,彼此无感知。例如,快速排序策略无需知道冒泡排序的存在。状态对象通常​​知晓其他状态​​,并能主动触发转换。例如,媒体播放器的 PlayingState(播放状态)可自行切换到 PausedState(暂停状态)。
使用场景算法可能变化且应由客户端选择时对象行为需要根据其生命周期演变时

4. 策略模式适用场景

在以下情况使用策略模式:
• 需要支持多种实现方式(算法)
• 需在运行时切换逻辑
• 希望遵循开闭原则
• 要避免if-else或switch语句膨胀

优缺点分析
优点

• 运行时切换算法
• 符合单一职责原则,代码更清晰
• 添加新算法不影响核心逻辑
• 便于测试和扩展

缺点
• 需要创建更多类
• 客户端必须了解策略选择
• 对简单任务可能过度设计

5. 总结

策略模式是管理算法变化的优雅方案。通过将行为委托给策略类,避免了if-else语句的混乱。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/92536.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/92536.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/92536.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL基础知识总结

一、MySQL简述 数据库 是一个有组织的集合,用于存储和管理数据的系统。它是一个软件系统,被设计用来存储、检索和管理数据,并提供数据的快速访问和处理。数据库可以被看作是一种特殊的文件系统,但与传统的文件系统不同的是&#…

数据仓库命名规范

1. 概述 数据模型是数据管理的分析工具和交流的有力手段;同时,还能够很好地保证数据的一致性,是实现商务智能(Business Intelligence)的重要基础。因此建立、管理一个企业级的数据模型,应该遵循标准的命名…

FlinkSQL Joins全解析

1. Lookup Join用途:用于流表与外部维表(静态或缓慢变化表)的关联(如 MySQL、HBase 等)。特点:通过 实时查询外部存储 获取维度数据。仅支持 处理时间(Processing Time)语义&#xf…

【FileZilla】基于 FTP 的 Windows 和 Linux 文件传输

在嵌入式开发过程中我们经常需要在 Windows 和 Linux 下进行文件传输,本文就介绍一种通过 FTP 实现 Windows 和 Linux 文件传输的方法。 Windows 为物理主机,Linux 是在 Vmware 虚拟机中安装运行的 Ubuntu,版本为 18.04。 Ubuntu 安装 FTP …

【GPT入门】第42课 ollama安装与运行llama3模型

【GPT入门】第42课 ollama安装与运行llama3模型1. 安装ollama2.运行模型3.测试模型3.1 直接在命令行交互3.2 openai接口1. 安装ollama https://ollama.com/ 选download, 选linux 执行安装命令: curl -fsSL https://ollama.com/install.sh | sh2.运行模型 启动服…

Lua语言元表、协同程序

元表元表的定义允许我们改变table的行为。setmetatable(普通表,元表)-- 元表a {"a","b","c"} -- 普通表 b {} --元表c setmetatable(a,b)print("------------------------")f {}print("f:",f)d setmetatabl…

[已解决]VSCode右键菜单消失恢复

前言 莫名其妙,好似VSCode自动更新以后,右键菜单就失效了,重装也无果. 手动搞一个吧 保存下面代码到桌面修复VSCODE右键菜单.reg,双击运行即可. Windows Registry Editor Version 5.00[HKEY_CLASSES_ROOT\Directory\Background\shell\VSCode]"使用 VSCode 打开""…

什么是浏览器标识?

浏览器标识 层面一:网络层指纹 (HTTP/TLS) 这是最基础的指纹,即使不用浏览器,只用Go的 net/http 发请求也会留下。HTTP Headers (请求头): User-Agent: 最著名的标识,声明自己是什么浏览器。很容易伪造,但也很容易被识…

五十八、【Linux系统nginx服务】nginx代理服务器、nginx优化

Nginx代理技术全景图 #mermaid-svg-0dRktnHYPXypO9xB {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-0dRktnHYPXypO9xB .error-icon{fill:#552222;}#mermaid-svg-0dRktnHYPXypO9xB .error-text{fill:#552222;stroke…

[0CTF 2016]piapiapia

usernamepassword回显推断admin123Invalid user name or passwordadmin123Invalid user name or passwordadmin123Invalid user name or passworda123Invalid user name说明username是adminadmin1Invalid password这很奇怪了admin0200?admin11Invalid user name or …

人工智能系列(7)人工神经网络中的无监督学习

一. 无监督学习简介神经网络的一个关键属性是能够从环境中学习,并在不断学习的过程中持续改善性能。在无监督学习(又称自组织学习,self-organized learning)中,网络无需外部教师提供目标输出,而是通过对输入…

250810-OpenWebUI集成Dify应用

A. 最终效果 B. 环境配置 配置并启动Open-WebUI 随后浏览器访问:http://localhost:8080 pip install open-webui open-webui serve配置并启动Pipelines Pipelines默认占用80端口相比于Docker的启动方式,可以在相同的命令行中,查看pipelines …

day22|学习前端ts语言

抽象类,继承。不能创造实例class类:属性声明,构造器,方法,实例继承super()override重写父类继承的方法声明提升(hoisting)同一个js作用域内部,编译阶段把函数…

【网络安全】CTF——[网鼎杯2018]Unfinish-SQL注入-二次注入

目录 一、前言 二、环境 三、复现 3.1寻找注入点 3.2尝试盲注 3.3正则限制 3.4脚本注入获取flag 四、总结 一、前言 前两天复现了一道CTF题目[网鼎杯 2018]Comment,今天继续来学习一下SQL二次注入。 二、环境 BUUCTF在线评测 三、…

【langchain】如何给langchain提issue和提pull request?

什么是issue? 可以这么理解,bug是issue的子集。issue可以包含bug\feature\sercurity and others. https://github.com/langchain-ai/langchain/issues/32484 什么是pull request? 其实我真不是很理解,但不妨我来提pr https://github.com/langchain-ai/…

MySQL的存储引擎:

目录 InooDB引擎: MyISAM引擎: InooDB引擎与MyISAM存储引擎的区别: Archive引擎: Blackhole引擎: CSV引擎: Memory引擎: Federated引擎: Merge引擎: NDB引擎&a…

Mock与Stub

一、核心概念与差异对比特性MockStub核心目的验证对象间的交互行为提供预定义的固定响应验证重点方法调用次数、参数、顺序不关注调用过程,只关注结果行为模拟可编程的智能模拟静态的简单响应适用场景验证协作关系隔离依赖、提供固定数据复杂性较高(需要…

香港服务器容器网络插件的多节点通信性能基准测试

香港服务器容器网络插件的多节点通信性能基准测试在云计算和容器化技术快速发展的今天,香港服务器因其优越的地理位置和网络环境,成为众多企业部署容器服务的首选。本文将深入探讨香港服务器环境下容器网络插件的多节点通信性能,通过详实的基…

Vue3 学习教程,从入门到精通,Vue 3 全局 API 语法知识点及案例详解(32)

Vue 3 全局 API 语法知识点及案例详解 Vue 3 提供了丰富的全局 API,用于创建应用实例、注册全局组件、指令、插件等。以下将详细介绍 Vue 3 的主要全局 API,并结合详细的案例代码进行说明。每个案例代码都包含中文注释,帮助初学者更好地理解…

UE5多人MOBA+GAS 41、制作一个飞弹,添加准心索敌

文章目录添加新角色(不写了)创建一个发射技能创建一个飞弹类添加击中特效添加准星UI获取瞄准目标添加新角色(不写了) 将原本的机器人蓝图改为BP_PlayerCharacter,以此创建子蓝图 创建动画蓝图模板(具体就…