设计模式:策略模式(C#、JAVA、JavaScript、C++、Python、Go、PHP)
简介:
策略模式,它是一种行为型设计模式,它定义了算法族,分别封装起来,让它们之间可以互相替换。策略模式让算法的变化独立于使用算法的客户,降低了耦合,增加了系统的可维护性和可扩展性。
策略模式的结构包括三种角色:
1、策略(Strategy):策略是一个接口,该接口定义了算法标识。
2、具体策略(ConcreteStrategy):具体策略是实现策略接口的类,具体策略实现策略接口所定义的抽象方法,即给出算法标识的具体算法。
3、上下文(Context):上下文是依赖于策略接口的类,即上下文包含有策略声明的变量。上下文中提供了一个方法,该方法委托策略变量调用具体策略所实现的策略接口中的方法。
策略模式的使用场景:
1、针对同一类型问题的多种处理方式,但具体行为有差别时。
2、需要安全地封装多种同一类型的操作时。
3、出现同一抽象类有多个子类,而又需要使用 if-else 或者 switch-case 来选择具体子类时。
4、当业务功能是客户程序的一个难以分割的成分时,增加新的业务算法或改变现有算法将十分困难。
5、当不同的时候需要不同的算法,我们不想支持我们并不使用的业务算法时。
6、当算法使用了客户不应该知道的数据时。
7、当一个类定义了很多行为,而且这些行为在这个类里的操作以多个条件语句的形式出现时。
总之,策略模式是一种非常实用的设计模式,可以用于封装各种类型的规则,并且可以在不同的时间应用不同的业务规则。
策略模式的创建步骤:
1、定义策略接口:首先需要定义一个策略接口,该接口中包含算法的方法。
2、创建具体策略类:根据策略接口,创建实现具体算法的类。
3、创建上下文类:上下文类负责维护和查询策略对象,并在具体策略类中注入策略对象。
4、在上下文类中注入策略对象:通过构造函数或者setter方法,将策略对象注入到上下文类中。
5、在客户端中创建上下文对象:在客户端中创建上下文对象,并将具体策略对象注入到上下文对象中。
6、客户端调用上下文对象:客户端通过上下文对象调用具体策略对象的方法,实现算法的调用。
以上是策略模式的基本创建步骤,具体实现方式可能会因语言和需求而有所不同。
策略模式的优点,主要包括:
1、提供了对“开闭原则”的完美支持,可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为。
2、提供了管理相关的算法族的办法,恰当使用继承可以把算法族的公共代码转移到父类里面,从而避免重复的代码。
3、提供了可以替换继承关系的办法,使得系统更加灵活和可维护。
4、使用策略模式可以避免使用多重条件转移语句,如 if...else 语句、switch...case 语句。
5、可以提供相同行为的不同实现,客户可以根据不同时间或空间要求选择不同的实现方式。
策略模式的缺点,主要包括:
1、客户端必须知道所有的策略类,并自行决定使用哪一个策略类,这可能违反了“开闭原则”。
2、策略模式会造成产生很多策略类,增加了系统的复杂性和维护成本。
3、在实现上,策略模式需要使用继承和多态,这会增加代码的复杂性和实现的难度。
4、在使用策略模式时,需要注意策略的正确性和稳定性,因为不同的策略可能会对系统的行为产生不同的影响。
总之,策略模式虽然可以提高系统的灵活性和可维护性,但也存在一些缺点需要注意。在使用策略模式时,需要根据具体情况进行权衡和考虑。

示例:
一、C#策略模式
以下是一个示例,展示了如何在C#中实现策略模式:
//定义策略接口
public interface Strategy
{ void Execute();
}
//创建具体策略类
public class ConcreteStrategyA : Strategy
{ public void Execute() { Console.WriteLine("执行策略A"); }
} public class ConcreteStrategyB : Strategy
{ public void Execute() { Console.WriteLine("执行策略B"); }
}
//创建上下文类
public class Context
{ private Strategy strategy; public Context(Strategy strategy) { this.strategy = strategy; } public void SetStrategy(Strategy strategy) { this.strategy = strategy; } public void DoSomething() { strategy.Execute(); }
}
//在客户端中创建上下文对象并注入具体策略对象
public class Client{public void Test(){Context context = new Context(new ConcreteStrategyA()); context.DoSomething(); // 输出:执行策略A context.SetStrategy(new ConcreteStrategyB()); context.DoSomething(); // 输出:执行策略B}
}
二、java策略模式
策略模式通常通过以下方式实现:
//定义策略接口
public interface Strategy { void execute();
}
//创建具体策略类
public class ConcreteStrategyA implements Strategy { @Override public void execute() { System.out.println("执行策略A"); }
} public class ConcreteStrategyB implements Strategy { @Override public void execute() { System.out.println("执行策略B"); }
}
//创建上下文类
public class Context { private Strategy strategy; public Context(Strategy strategy) { this.strategy = strategy; } public void setStrategy(Strategy strategy) { this.strategy = strategy; } public void doSomething() { strategy.execute(); }
}
//在客户端中创建上下文对象并注入具体策略对象
public class Main { public static void main(String[] args) { Context context = new Context(new ConcreteStrategyA()); context.doSomething(); // 输出:执行策略A context.setStrategy(new ConcreteStrategyB()); context.doSomething(); // 输出:执行策略B}
}
三、javascript策略模式
在JavaScript中,策略实现方式如下:
//定义策略接口
function Strategy(execute) { this.execute = execute;
}
//创建具体策略类
class ConcreteStrategyA extends Strategy { constructor() { super(this.execute); } execute() { console.log('执行策略A'); }
} class ConcreteStrategyB extends Strategy { constructor() { super(this.execute); } execute() { console.log('执行策略B'); }
}
//创建上下文类
class Context { constructor(strategy) { this.strategy = strategy; } setStrategy(strategy) { this.strategy = strategy; } doSomething() { this.strategy.execute(); }
}//在客户端中创建上下文对象并注入具体策略对象
const context = new Context(new ConcreteStrategyA());
context.doSomething(); // 输出:执行策略A
context.setStrategy(new ConcreteStrategyB());
context.doSomething(); // 输出:执行策略B
四、C++策略模式
以下是在C++中实现策略模式:
//定义策略接口
class Strategy {
public: virtual void execute() = 0;
};
//创建具体策略类
class ConcreteStrategyA : public Strategy {
public: void execute() override { cout << "执行策略A" << endl; }
}; class ConcreteStrategyB : public Strategy {
public: void execute() override { cout << "执行策略B" << endl; }
};
//创建上下文类
class Context {
public: Context(Strategy* strategy) : strategy_(strategy) {} void setStrategy(Strategy* strategy) { strategy_ = strategy; } void doSomething() { strategy_->execute(); }
private: Strategy* strategy_;
};
//在客户端中创建上下文对象并注入具体策略对象
int main() { Context context(new ConcreteStrategyA()); context.doSomething(); // 输出:执行策略A context.setStrategy(new ConcreteStrategyB()); context.doSomething(); // 输出:执行策略B delete context.strategy_; delete context; return 0;
}
五、python策略模式
以下是在python中实现策略模式:
//定义策略接口
from abc import ABC, abstractmethod class Strategy(ABC): @abstractmethod def execute(self): pass//创建具体策略类
class ConcreteStrategyA(Strategy): def execute(self): print("执行策略A") class ConcreteStrategyB(Strategy): def execute(self): print("执行策略B")//创建上下文类
class Context: def __init__(self, strategy): self.strategy = strategy def set_strategy(self, strategy): self.strategy = strategy def do_something(self): self.strategy.execute()//在客户端中创建上下文对象并注入具体策略对象
context = Context(ConcreteStrategyA())
context.do_something() # 输出:执行策略A
context.set_strategy(ConcreteStrategyB())
context.do_something() # 输出:执行策略B
六、go策略模式
以下是一个示例,展示了如何在go中实现策略模式:
//定义策略接口
type Strategy interface { Execute()
}
//创建具体策略类
type ConcreteStrategyA struct{} func (s *ConcreteStrategyA) Execute() { fmt.Println("执行策略A")
} type ConcreteStrategyB struct{} func (s *ConcreteStrategyB) Execute() { fmt.Println("执行策略B")
}
//创建上下文类
type Context struct { strategy Strategy
} func (c *Context) SetStrategy(strategy Strategy) { c.strategy = strategy
} func (c *Context) DoSomething() { c.strategy.Execute()
}
//在客户端中创建上下文对象并注入具体策略对象
func main() { context := &Context{} context.SetStrategy(&ConcreteStrategyA{}) context.DoSomething() // 输出:执行策略A context.SetStrategy(&ConcreteStrategyB{}) context.DoSomething() // 输出:执行策略B
}
七、PHP策略模式
以下是一个示例,展示了如何在PHP中实现策略模式:
//定义策略接口
interface Strategy { public function execute();
}
//创建具体策略类
class ConcreteStrategyA implements Strategy { public function execute() { echo "执行策略A"; }
} class ConcreteStrategyB implements Strategy { public function execute() { echo "执行策略B"; }
}
//创建上下文类
class Context { private $strategy; public function __construct(Strategy $strategy) { $this->strategy = $strategy; } public function setStrategy(Strategy $strategy) { $this->strategy = $strategy; } public function doSomething() { $this->strategy->execute(); }
}
//在客户端中创建上下文对象并注入具体策略对象
$context = new Context(new ConcreteStrategyA());
$context->doSomething(); // 输出:执行策略A
$context->setStrategy(new ConcreteStrategyB());
$context->doSomething(); // 输出:执行策略B
通过以上步骤,我们实现了策略模式,使得算法可以独立于使用它的客户端,并且可以在不修改原有系统的基础上选择算法或行为。这种设计模式使得程序更加灵活和可维护。策略模式体现了开闭原则和里氏替换原则,各个策略实现都是兄弟关系,实现了同一个接口或者继承了同一个抽象类。这样只要使用策略的客户端保持面向抽象编程,就可以动态地切换不同的策略实现以进行替换。
《完结》
相关文章:
设计模式:策略模式(C#、JAVA、JavaScript、C++、Python、Go、PHP)
简介: 策略模式,它是一种行为型设计模式,它定义了算法族,分别封装起来,让它们之间可以互相替换。策略模式让算法的变化独立于使用算法的客户,降低了耦合,增加了系统的可维护性和可扩展性。 策…...
详解如何快速查询Node.js版本信息(六种方法)
Node.js是一款基于Chrome V8引擎的快速、轻量级的JavaScript运行时。随着应用程序规模越来越庞大,Node.js版本的更新也日益频繁。这篇文章旨在帮助开发者们快速查询Node.js版本信息。 一、使用node命令查询版本信息 node命令提供了一个参数-v,可以在控…...
YOLOV8目标检测——最全最完整模型训练过程记录
文章目录 前言1 下载yolov8([网址](https://github.com/ultralytics/ultralytics))2 配置conda环境3 用pycharm打开文件3 训练自己的YOLOV8数据集4 run下运行完了之后没有best.pt文件5 导出为onnx文件6 yolov8应用完整案例(免费且包含源代码、…...
【C语言】用函数实现模块化程序设计
前言:如果把所有的程序代码都写在一个主函数(main函数)中,就会使主函数变得庞杂、头绪不清,使阅读和维护程序变得困难。此外,有时程序中要多次实现某一功能,如果重新编写实现此功能就会使得程序冗长、不精炼。 &#x…...
忆联SR-IOV解决方案:助力云数据中心节能提效,向“绿”而行
随着AI时代的到来,云数据中心如何实现节能提效正成为热门话题。其中,SR-IOV技术凭借灵活度高以及可节约虚拟化业务算力等优势,是打造绿色低碳云数据中心的重要解决方案之一。 一、什么是SR-IOV 技术 SR-IOV 是由国际组织 PCI-SIG 组织定义的…...
LeetCode:1402. 做菜顺序、2316. 统计无向图中无法互相到达点对数
1. 1402 做菜顺序 题目详细为: 一个厨师收集了他 n 道菜的满意程度 satisfaction ,这个厨师做出每道菜的时间都是 1 单位时间。 一道菜的 「 like-time 系数 」定义为烹饪这道菜结束的时间(包含之前每道菜所花费的时间)乘以这道菜…...
【消费战略】解读100个食品品牌|意面突起,“空刻”的品类心智占位!
空刻意面,一个开创意大利面速食化的新消费品牌,凭借着核心大单品意大利面,在过去短短的几年中,获得不俗的市场成绩和品牌影响力,占领了空刻意面的消费心智: 2019年,AIRMETER氢刻意面上线天猫旗舰…...
地图金字塔所在块的经纬度方位
地图金字塔所在块的经纬度方位 算法 #define LON_SPAN 360.0 // 开始经度(最左端) #define LAT_SPAN 180.0 #define GLOBAL_LEFT -180.0 // 开始纬度(最上端) #define GLOBAL_TOP 90.0 #define GLOBAL_RIGHT 180.0 #define GLOBAL_BOTTOM -90.0 // 地球的纬度跨度(180-(-180))…...
【干货】Java函数式编程公式大全,收藏学习!
函数操作是现代编程领域中的核心概念之一,它以类似 Excel 表格的方式进行数据处理和计算。它的特点是使用公式和函数来描述数据之间的关系和计算逻辑;它允许我们以更高效、更有组织的方式管理和处理数据。 在函数式编程中,数据被组织成表格的…...
django基于Python的房价预测系统+爬虫+大屏可视化分析
欢迎大家点赞、收藏、关注、评论 文章目录 前言一、项目介绍二、开发环境三、功能需求分析1 数据采集功能设计2数据管理功能设计3爬虫功能需求分析4 数据可视化功能需求分析数据库表的设计 四、核心代码五、效果图六、文章目录 前言 房价是一个国家经济水平的重要体现ÿ…...
异地组网企业怎么办理手续?
对于那些具有异地分支机构的企业来说,SDWAN(Software Defined Wide Area Network)可以是 提供高性能通信和数据传输的理想解决方案。那么,对于企业来说,SDWAN异地组网需要办理哪 些手续呢?下面将介绍一些关键的办理步骤。 1. 资质准备&…...
Android 13.0 根据包名授予OP_REQUEST_INSTALL_PACKAGES权限
1.概述 在系统13.0的定制化开发中,对于在app中调用安装第三方app的时候,会在这时弹出安装未知来源弹窗,需要默认授予REQUEST_INSTALL_PACKAGES 权限,来安装第三方app的安装未知来源权限,所以就是今天需要解决的这个问题 2.根据包名授予OP_REQUEST_INSTALL_PACKAGES的核心…...
民安智库(湖北知名满意度测评公司)乘客高铁出行调查:从需求到满意
随着科技的飞速发展,高铁已成为我们日常出行的重要选择。然而,什么样的服务才是乘客真正需要的?什么样的调查才能真实反映乘客的感受?民安智库(政务服务第三方评估公司)作为一家中国独立第三方调研咨询的公…...
Oracle的dbms.rls实现数据访问控制
在大部份系统中,权限控制主要定义为模块进入权限的控制和数据列访问权限的控制(如:某某人可以进入某个控制,仓库不充许查看有关部门的字段等等)。 但在某些系统中,权限控制又必须定义到数据行访问权限的控制,此需求一般…...
Python 自定义函数的基本步骤
一、Python 自定义函数的基本步骤 1、什么是函数 函数,其实我们一开始学 Python 的时候就接触过。 不过我们使用的大多数都是 Python 的内置函数。 比如基本每个章节都会出现的 print() 函数。 而现在,我们主要学习的是自定义函数。 各位有没有想过…...
阿里云新品云服务器实例,经济型e实例,价格便宜,性价比高
前不久,阿里云推出了一款全新云服务器实例,他是阿里云面向个人开发者、学生、小微企业,在中小型网站建设、开发测试、轻量级应用等场景推出的全新入门级云服务器,基于“飞天CIPU”黄金技术架构设计,可轻松满足网站建设…...
统信操作系统UOS上安装arm64版nginx
原文链接:统信操作系统UOS上安装arm64版nginx hello,大家好啊,今天给大家带来一篇在统信桌面操作系统UOS上安装arm64版nginx的文章,本篇文章主要是给大家提供一种下载离线nginx软件包的方法,拿到软件包可以去不能链接互…...
2017年高热度编程语言简介
世上语言千千万,我却独爱这一种!”这句话用来形容程序员和编程语言之间的爱恨情仇实在是再精准不过了。根据GitHub 2016年的开源报告,其上所有开源项目共包含了316种编程语言,这是一个什么概念呢?举个例子来说,世界上共有226个国…...
python爬虫入门(一)web基础
HTTP基本要点 HTTP请求,由客户端向服务端发出,可以分为 4 部分内容:请求方法(Request Method)、请求的网址(Request URL)、请求头(Request Headers)、请求体(…...
利用TreeMap来解决P3029 [USACO11NOV] Cow Lineup S
P3029 [USACO11NOV] Cow Lineup S - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 好了,我们首先要统计奶牛的种类数量n,好与接下来我们记录一个范围内的奶牛的数量作比较,一旦我们统计范围内的奶牛的数量m达到我们刚开始记录的奶牛的数量n我…...
保姆级教程:用Proteus 8.13和STM32F103C8T6复刻一个智能烟雾报警器(附源码)
从零构建基于STM32的智能烟雾报警系统:Proteus仿真与硬件实战指南 在电子设计领域,能够将虚拟仿真与实物开发无缝衔接的能力已成为工程师的核心竞争力。本文将带您完整走通从Proteus仿真到STM32硬件实现的智能烟雾报警系统开发全流程,特别适合…...
Phi-3-mini-128k-instruct系统参数详解:温度(Temperature)与Top-p调优指南
Phi-3-mini-128k-instruct系统参数详解:温度(Temperature)与Top-p调优指南 刚接触Phi-3-mini这类大语言模型时,你可能会有这样的困惑:为什么同样的提示词,有时候模型回答得严谨专业,有时候又天…...
Beyond CNNs: How Vision Transformers Revolutionize Image Recognition at Scale
1. 视觉Transformer为何能超越CNN? 记得我第一次用ResNet50跑ImageNet分类时,被它的准确率惊艳到了。但当我尝试用ViT-L/16在同样数据集上训练时,测试集top-1准确率直接高出3个百分点——这相当于过去CNN架构迭代两三代的提升幅度。为什么这…...
OrCAD不同版本兼容性踩坑记:为什么17.4报SPCODD-385,而16.6就没事?
OrCAD版本兼容性深度解析:从SPCODD-385错误看工程文件迁移策略 上周团队里新来的硬件工程师小王遇到了一个奇怪现象:同一份设计文件在OrCAD 17.4中报出十几个SPCODD-385错误,换到16.6环境却只有零星提示。这让我想起三年前公司EDA工具升级时…...
终极指南:在Mac上免费本地运行Stable Diffusion的完整解决方案
终极指南:在Mac上免费本地运行Stable Diffusion的完整解决方案 【免费下载链接】MochiDiffusion Run Stable Diffusion on Mac natively 项目地址: https://gitcode.com/gh_mirrors/mo/MochiDiffusion 还在为AI绘画工具的复杂设置和隐私担忧而烦恼吗…...
GraphGPT部署与优化:解决20秒延迟问题的终极方案
GraphGPT部署与优化:解决20秒延迟问题的终极方案 【免费下载链接】GraphGPT Extrapolating knowledge graphs from unstructured text using GPT-3 🕵️♂️ 项目地址: https://gitcode.com/gh_mirrors/gr/GraphGPT GraphGPT是一款利用GPT-3从非…...
Spring Cloud Sleuth实战:5分钟搞定分布式调用链追踪(附Zipkin可视化)
Spring Cloud Sleuth与Zipkin:5分钟构建零侵入式分布式追踪系统 微服务架构下,一次用户请求可能跨越数十个服务节点,传统的日志排查如同大海捞针。上周我们线上环境出现订单状态异常,运维团队花了整整8小时才定位到是支付服务与风…...
Pixel Dimension Fissioner 创意编程:结合Node.js构建实时图像生成服务
Pixel Dimension Fissioner 创意编程:结合Node.js构建实时图像生成服务 1. 为什么需要实时图像生成服务 电商平台需要每天生成上千张商品展示图,社交媒体运营要快速产出吸引眼球的视觉内容,广告公司面临紧急修改需求...这些场景都在呼唤一个…...
大模型之Linux服务器部署大模型富
一、各自优势和对比 这是检索出来的数据,据说是根据第三方评测与企业数据,三款产品在代码生成质量上各有侧重: 产品 语言优势 场景亮点 核心差异 百度 Comate C核心代码质量第一;Python首生成率达92.3% SQL生成准确率提升35%&…...
3步实现PCB可视化BOM管理:InteractiveHtmlBom实战指南
3步实现PCB可视化BOM管理:InteractiveHtmlBom实战指南 【免费下载链接】InteractiveHtmlBom Interactive HTML BOM generation plugin for KiCad, EasyEDA, Eagle, Fusion360 and Allegro PCB designer 项目地址: https://gitcode.com/gh_mirrors/in/InteractiveH…...
