当前位置: 首页 > news >正文

设计模式:策略模式(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)

简介&#xff1a; 策略模式&#xff0c;它是一种行为型设计模式&#xff0c;它定义了算法族&#xff0c;分别封装起来&#xff0c;让它们之间可以互相替换。策略模式让算法的变化独立于使用算法的客户&#xff0c;降低了耦合&#xff0c;增加了系统的可维护性和可扩展性。 策…...

详解如何快速查询Node.js版本信息(六种方法)

Node.js是一款基于Chrome V8引擎的快速、轻量级的JavaScript运行时。随着应用程序规模越来越庞大&#xff0c;Node.js版本的更新也日益频繁。这篇文章旨在帮助开发者们快速查询Node.js版本信息。 一、使用node命令查询版本信息 node命令提供了一个参数-v&#xff0c;可以在控…...

YOLOV8目标检测——最全最完整模型训练过程记录

文章目录 前言1 下载yolov8&#xff08;[网址](https://github.com/ultralytics/ultralytics)&#xff09;2 配置conda环境3 用pycharm打开文件3 训练自己的YOLOV8数据集4 run下运行完了之后没有best.pt文件5 导出为onnx文件6 yolov8应用完整案例&#xff08;免费且包含源代码、…...

【C语言】用函数实现模块化程序设计

前言&#xff1a;如果把所有的程序代码都写在一个主函数(main函数)中&#xff0c;就会使主函数变得庞杂、头绪不清&#xff0c;使阅读和维护程序变得困难。此外&#xff0c;有时程序中要多次实现某一功能&#xff0c;如果重新编写实现此功能就会使得程序冗长、不精炼。 &#x…...

忆联SR-IOV解决方案:助力云数据中心节能提效,向“绿”而行

随着AI时代的到来&#xff0c;云数据中心如何实现节能提效正成为热门话题。其中&#xff0c;SR-IOV技术凭借灵活度高以及可节约虚拟化业务算力等优势&#xff0c;是打造绿色低碳云数据中心的重要解决方案之一。 一、什么是SR-IOV 技术 SR-IOV 是由国际组织 PCI-SIG 组织定义的…...

LeetCode:1402. 做菜顺序、2316. 统计无向图中无法互相到达点对数

1. 1402 做菜顺序 题目详细为&#xff1a; 一个厨师收集了他 n 道菜的满意程度 satisfaction &#xff0c;这个厨师做出每道菜的时间都是 1 单位时间。 一道菜的 「 like-time 系数 」定义为烹饪这道菜结束的时间&#xff08;包含之前每道菜所花费的时间&#xff09;乘以这道菜…...

【消费战略】解读100个食品品牌|意面突起,“空刻”的品类心智占位!

空刻意面&#xff0c;一个开创意大利面速食化的新消费品牌&#xff0c;凭借着核心大单品意大利面&#xff0c;在过去短短的几年中&#xff0c;获得不俗的市场成绩和品牌影响力&#xff0c;占领了空刻意面的消费心智&#xff1a; 2019年&#xff0c;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函数式编程公式大全,收藏学习!

函数操作是现代编程领域中的核心概念之一&#xff0c;它以类似 Excel 表格的方式进行数据处理和计算。它的特点是使用公式和函数来描述数据之间的关系和计算逻辑&#xff1b;它允许我们以更高效、更有组织的方式管理和处理数据。 在函数式编程中&#xff0c;数据被组织成表格的…...

django基于Python的房价预测系统+爬虫+大屏可视化分析

欢迎大家点赞、收藏、关注、评论 文章目录 前言一、项目介绍二、开发环境三、功能需求分析1 数据采集功能设计2数据管理功能设计3爬虫功能需求分析4 数据可视化功能需求分析数据库表的设计 四、核心代码五、效果图六、文章目录 前言 房价是一个国家经济水平的重要体现&#xff…...

异地组网企业怎么办理手续?

对于那些具有异地分支机构的企业来说&#xff0c;SDWAN(Software Defined Wide Area Network)可以是 提供高性能通信和数据传输的理想解决方案。那么&#xff0c;对于企业来说&#xff0c;SDWAN异地组网需要办理哪 些手续呢?下面将介绍一些关键的办理步骤。 1. 资质准备&…...

Android 13.0 根据包名授予OP_REQUEST_INSTALL_PACKAGES权限

1.概述 在系统13.0的定制化开发中,对于在app中调用安装第三方app的时候,会在这时弹出安装未知来源弹窗,需要默认授予REQUEST_INSTALL_PACKAGES 权限,来安装第三方app的安装未知来源权限,所以就是今天需要解决的这个问题 2.根据包名授予OP_REQUEST_INSTALL_PACKAGES的核心…...

民安智库(湖北知名满意度测评公司)乘客高铁出行调查:从需求到满意

随着科技的飞速发展&#xff0c;高铁已成为我们日常出行的重要选择。然而&#xff0c;什么样的服务才是乘客真正需要的&#xff1f;什么样的调查才能真实反映乘客的感受&#xff1f;民安智库&#xff08;政务服务第三方评估公司&#xff09;作为一家中国独立第三方调研咨询的公…...

Oracle的dbms.rls实现数据访问控制

在大部份系统中&#xff0c;权限控制主要定义为模块进入权限的控制和数据列访问权限的控制(如&#xff1a;某某人可以进入某个控制&#xff0c;仓库不充许查看有关部门的字段等等)。 但在某些系统中&#xff0c;权限控制又必须定义到数据行访问权限的控制&#xff0c;此需求一般…...

Python 自定义函数的基本步骤

一、Python 自定义函数的基本步骤 1、什么是函数 函数&#xff0c;其实我们一开始学 Python 的时候就接触过。 不过我们使用的大多数都是 Python 的内置函数。 比如基本每个章节都会出现的 print() 函数。 而现在&#xff0c;我们主要学习的是自定义函数。 各位有没有想过…...

阿里云新品云服务器实例,经济型e实例,价格便宜,性价比高

前不久&#xff0c;阿里云推出了一款全新云服务器实例&#xff0c;他是阿里云面向个人开发者、学生、小微企业&#xff0c;在中小型网站建设、开发测试、轻量级应用等场景推出的全新入门级云服务器&#xff0c;基于“飞天CIPU”黄金技术架构设计&#xff0c;可轻松满足网站建设…...

统信操作系统UOS上安装arm64版nginx

原文链接&#xff1a;统信操作系统UOS上安装arm64版nginx hello&#xff0c;大家好啊&#xff0c;今天给大家带来一篇在统信桌面操作系统UOS上安装arm64版nginx的文章&#xff0c;本篇文章主要是给大家提供一种下载离线nginx软件包的方法&#xff0c;拿到软件包可以去不能链接互…...

2017年高热度编程语言简介

世上语言千千万&#xff0c;我却独爱这一种!”这句话用来形容程序员和编程语言之间的爱恨情仇实在是再精准不过了。根据GitHub 2016年的开源报告&#xff0c;其上所有开源项目共包含了316种编程语言&#xff0c;这是一个什么概念呢?举个例子来说&#xff0c;世界上共有226个国…...

python爬虫入门(一)web基础

HTTP基本要点 HTTP请求&#xff0c;由客户端向服务端发出&#xff0c;可以分为 4 部分内容&#xff1a;请求方法&#xff08;Request Method&#xff09;、请求的网址&#xff08;Request URL&#xff09;、请求头&#xff08;Request Headers&#xff09;、请求体&#xff08…...

利用TreeMap来解决P3029 [USACO11NOV] Cow Lineup S

P3029 [USACO11NOV] Cow Lineup S - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 好了&#xff0c;我们首先要统计奶牛的种类数量n&#xff0c;好与接下来我们记录一个范围内的奶牛的数量作比较&#xff0c;一旦我们统计范围内的奶牛的数量m达到我们刚开始记录的奶牛的数量n我…...

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…...

【WiFi帧结构】

文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成&#xff1a;MAC头部frame bodyFCS&#xff0c;其中MAC是固定格式的&#xff0c;frame body是可变长度。 MAC头部有frame control&#xff0c;duration&#xff0c;address1&#xff0c;address2&#xff0c;addre…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例

使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件&#xff0c;常用于在两个集合之间进行数据转移&#xff0c;如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model&#xff1a;绑定右侧列表的值&…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?

在建筑行业&#xff0c;项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升&#xff0c;传统的管理模式已经难以满足现代工程的需求。过去&#xff0c;许多企业依赖手工记录、口头沟通和分散的信息管理&#xff0c;导致效率低下、成本失控、风险频发。例如&#…...

TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案

一、TRS收益互换的本质与业务逻辑 &#xff08;一&#xff09;概念解析 TRS&#xff08;Total Return Swap&#xff09;收益互换是一种金融衍生工具&#xff0c;指交易双方约定在未来一定期限内&#xff0c;基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

EtherNet/IP转DeviceNet协议网关详解

一&#xff0c;设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络&#xff0c;本网关连接到EtherNet/IP总线中做为从站使用&#xff0c;连接到DeviceNet总线中做为从站使用。 在自动…...

虚拟电厂发展三大趋势:市场化、技术主导、车网互联

市场化&#xff1a;从政策驱动到多元盈利 政策全面赋能 2025年4月&#xff0c;国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》&#xff0c;首次明确虚拟电厂为“独立市场主体”&#xff0c;提出硬性目标&#xff1a;2027年全国调节能力≥2000万千瓦&#xff0…...

【C++进阶篇】智能指针

C内存管理终极指南&#xff1a;智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...

STM32HAL库USART源代码解析及应用

STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...

协议转换利器,profinet转ethercat网关的两大派系,各有千秋

随着工业以太网的发展&#xff0c;其高效、便捷、协议开放、易于冗余等诸多优点&#xff0c;被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口&#xff0c;具有实时性、开放性&#xff0c;使用TCP/IP和IT标准&#xff0c;符合基于工业以太网的…...