【设计模式深度剖析】【4】【行为型】【策略模式】

文章目录

  • 策略模式
  • 定义
    • 英文原话
    • 直译
  • 角色
    • 类图
    • 策略接口`Strategy`:
    • 具体策略类
    • 上下文类Context
    • 测试类
  • 策略模式的应用
    • 策略模式的优点
    • 策略模式的缺点
    • 策略模式的使用场景

策略模式

策略模式(Strategy Pattern)

Strategy策略也称作Policy政策。

想象一下我们正在玩一个角色扮演游戏。在游戏中,我们的角色有多种技能可以选择,比如“火球术”、“冰霜箭”和“治愈术”。每种技能都有不同的效果和用途。现在,游戏设计师希望让我们能够随时切换这些技能以适应不同的战斗场景。

策略模式就是这样一种设计思想。它允许我们定义不同的“技能”(即策略),然后在游戏中根据需要随时切换使用哪种技能。这样,我们就可以更加灵活地应对各种战斗情况了。

同样地,在计费系统或商城促销活动中,策略模式也允许我们根据不同的条件选择不同的计费方式或优惠策略,使得系统更加灵活和可配置。

定义

英文原话

Define a family of algorithms, encapsulate each one, and make them interchangeable.

直译

定义一系列的算法,把它们一个个封装起来,并且是他们可相互替换(必然实现了相同的接口,不然无法相互替换,该接口就是策略接口)

本模式使得算法可独立于使用它的客户而变化。

角色

  1. 策略接口(Strategy):定义所有支持的算法的公共接口。
  2. 具体策略(ConcreteStrategy):实现策略接口的类,具体策略类实现了算法的具体逻辑。
  3. 上下文(Context):使用策略接口的类,也称为“上下文”或“客户端”。上下文类内部持有一个策略对象的引用,并且负责在需要的时候调用策略对象的算法。

类图

在这里插入图片描述

在策略模式中,我们可以将这三个角色用Java类来具体实现。以下是一个简化的策略模式示例,其中包含了Strategy(策略接口)、ConcreteStrategy(具体策略类)和Context(上下文类)的实现。

策略接口Strategy

// Strategy.java  
public interface Strategy {  
    void executeStrategy();  
}

具体策略类

这里假设有两个具体策略类ConcreteStrategyAConcreteStrategyB

// ConcreteStrategyA.java  
public class ConcreteStrategyA implements Strategy {  
    @Override  
    public void executeStrategy() {  
        System.out.println("执行策略A");  
        // 策略A的具体实现  
    }  
}  
  
// ConcreteStrategyB.java  
public class ConcreteStrategyB implements Strategy {  
    @Override  
    public void executeStrategy() {  
        System.out.println("执行策略B");  
        // 策略B的具体实现  
    }  
}

上下文类Context

它持有一个策略对象的引用,并提供了设置策略和执行策略的方法:

// Context.java  
public class Context {  
    private Strategy strategy;  
  
    // 构造函数  
    public Context(Strategy strategy) {  
        this.strategy = strategy;  
    }  
  
    // 设置策略  
    public void setStrategy(Strategy strategy) {  
        this.strategy = strategy;  
    }  
  
    // 执行策略  
    public void executeStrategy() {  
        strategy.executeStrategy();  
    }  
}

测试类

现在,我们可以编写一个示例来展示如何使用策略模式:

// StrategyPatternDemo.java  
public class StrategyPatternDemo {  
    public static void main(String[] args) {  
        // 创建策略对象  
        Strategy strategyA = new ConcreteStrategyA();  
        Strategy strategyB = new ConcreteStrategyB();  
  
        // 创建上下文对象并设置策略  
        Context context = new Context(strategyA);  
        context.executeStrategy(); // 输出:执行策略A  
  
        // 修改策略  
        context.setStrategy(strategyB);  
        context.executeStrategy(); // 输出:执行策略B  
    }  
}

/* Output:
执行策略A
执行策略B
*///~

在这个示例中,Context类可以根据需要改变其内部持有的Strategy对象,从而改变其行为。

这是策略模式的核心思想:将算法的使用与算法的实现分离开来,使得算法可以独立于使用它的客户端变化。

策略模式的应用

策略模式是一种行为型设计模式,它定义了一系列的算法,并将每一个算法封装起来,使它们可以互相替换。在软件系统中,策略模式使得算法可以独立于使用它的客户端变化。

策略模式的优点

  1. 算法自由切换:由于策略类实现了同一个接口,因此它们之间可以自由切换,这使得系统更加灵活和可维护。
  2. 易于扩展:当需要增加新的算法时,只需要实现该接口即可,符合开闭原则。
  3. 避免使用多重条件语句:使用策略模式可以避免在代码中出现大量的if-else语句,使代码更加清晰、简洁和易于维护。
  4. 提高算法的保密性和安全性:客户端只需要知道它使用了哪些算法,而不需要知道这些算法的具体实现细节,这有助于保护算法的安全性和保密性。

策略模式的缺点

  1. 客户端必须知道所有的策略类:客户端需要了解并决定使用哪一个策略类,这可能会增加客户端的复杂性。
  2. 可能造成策略类过多:当系统中存在大量的策略时,可能会导致策略类过多,增加了系统的复杂性。

策略模式的使用场景

  1. 计费系统:对于不同用户类型和消费金额采用不同的计费方式,可以使用策略模式来定义不同的计费策略。
  2. 游戏开发中的角色技能系统:不同角色拥有不同的技能,可以根据角色的选择使用不同的技能策略进行攻击或防御。
  3. 商城促销活动:根据不同的促销活动采取不同的优惠方式,如打折、满减等,策略模式可以方便地管理和切换这些优惠策略。
  4. 需要动态选择算法的场景:当系统中需要根据不同的条件选择不同的算法进行计算时,策略模式可以提供一个灵活的解决方案。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/686170.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Springboot jar运行时,将jar内的文件拷贝到文件系统中

背景 因为执行需要,需要把jar内templates文件夹下的的文件夹及文件加压到宿主机器的某个路径下, 以便执行对应的脚本文件 PS: 通过类加载器等方式,直接getFile遍历文件,在idea中运行是没问题的,但是当打包成jar运行就会…

【JavaEE】留言板与图书管理系统

目录 留言板1. 准备工作2. 约定前后端交互接口lombok3. 服务器代码4. 调整前端页面代码 图书管理系统1. 准备工作2. 约定前后端交互接口3. 服务器代码4. 调整前端页面代码 留言板 需求: 界⾯如下图所⽰ 输⼊留⾔信息, 点击提交. 后端把数据存储起来.⻚⾯展⽰输⼊的表⽩墙的信…

Mysql使用中的性能优化——搭建Mysql的监测服务

大纲 环境安装配置Mysql安装设置root密码新增远程访问账户修改绑定地址重启 新增 MySQL Server Exporter 用户 安装启动mysqld_exporter安装启动新增配置启动 安装启动Prometheus创建用户下载并解压修改配置启动 安装启动grafana安装启动 测试参考资料 抛开场景和数据&#xff…

【YOLOv8改进[CONV]】SPDConv助力YOLOv8目标检测效果 + 含全部代码和详细修改方式 + 手撕结构图

本文将使用SPDConv助力YOLOv8目标检测效果的实践,文中含全部代码、详细修改方式以及手撕结构图。助您轻松理解改进的方法。 改进前和改进后的参数对比: 目录 一 SPDConv 二 SPDConv助力YOLOv8目标检测效果 1 整体修改 ① 添加SPDConv.py文件 ② 修改ultralytics/nn/tas…

笔记95:车辆横向动力学方程转化为误差形式 -- 详细推导过程

1. 非误差型车辆横向动力学方程 注:关于轮胎侧偏刚度的正负 深蓝课程推导得到的车辆横向动力学返程使用的轮胎侧偏刚度是默认为正数;老王课程推导得到的车辆横向动力学方程使用的轮胎侧偏刚度是默认为负数; 1.1 深蓝课程推导得到的方程&…

【Qt知识】部分QWidget属性表格

QWidget是Qt库中所有图形用户界面组件的基类,它提供了大量属性以供自定义和配置控件的行为和外观。下面列出了一些主要的QWidget属性及其作用。 属性 作用 accessibleName 控件的辅助技术名称,用于无障碍访问。 accessibleDescription 控件的辅助技…

18 - 各赛事的用户注册率(高频 SQL 50 题基础版)

18 - 各赛事的用户注册率 -- 注册率注册用户数/所有用户数 selectr.contest_id,round(100*count(*)/(select count(*) from Users),2) percentage from Register r group by r.contest_id order bypercentage desc,r.contest_id ASC;

网鼎杯 2020 玄武组 SSRFMe

复习一下常见的redis主从复制 主要是redis伪服务器的选择和一些小坑点 <?php function check_inner_ip($url) { $match_resultpreg_match(/^(http|https|gopher|dict)?:\/\/.*(\/)?.*$/,$url); if (!$match_result) { die(url fomat error); } try { …

3D Web轻量化平台HOOPS Web Platform助力Rapid DCS迅速推出成本与碳排放估算产品

英国公司Rapid DCS利用HOOPS Web平台在短短六个月内成功开发出创新的云解决方案Sterling&#xff0c;旨在帮助建筑行业客户高效地估算成本和计算碳排放。 Rapid DCS&#xff0c;一家总部位于英国的公司&#xff0c;专注于为建筑环境领域的客户提供全面的数字化解决方案和服务。…

NextJs 实现自定义点火操作

NextJs 实现自定义点火操作 前言实现自定义点火 前言 我希望在Nextjs 启动的时候&#xff0c;能够自定义实现一些项目的初始化逻辑&#xff0c;也可以说是一些点火操作&#xff0c;比如资源的加载&#xff0c;数据的初始化等操作。 实现自定义点火 我们可以在根目录下创建一…

22 - 游戏玩法分析 IV(高频 SQL 50 题基础版)

22 - 游戏玩法分析 IV 考点&#xff1a; 聚合函数 # 日期相加 date_add(min(event_date),INTERVAL 1 DAY) select round(count(distinct player_id)/(select count(distinct player_id) from Activity),2) fraction fromActivity where-- 如果日期加一天的数据能在表中…

界面组件DevExpress Reports v23.2增强用户体验 - 轻松导航Web设计器

DevExpress Reporting是.NET Framework下功能完善的报表平台&#xff0c;它附带了易于使用的Visual Studio报表设计器和丰富的报表控件集&#xff0c;包括数据透视表、图表&#xff0c;因此您可以构建无与伦比、信息清晰的报表。 DevExpress Reports v23.2(我们最近的主要更新…

C++ 11【右值引用】

&#x1f493;博主CSDN主页:麻辣韭菜&#x1f493;   ⏩专栏分类&#xff1a;C修炼之路⏪   &#x1f69a;代码仓库:C高阶&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习更多C知识   &#x1f51d;&#x1f51d; 1.C 11 简介 目录 1.C 11 简介 2. 统一的列表…

小程序自定义marker弹出框教程

需求背景 微信小程序开发&#xff0c;需要使用腾讯地图显示自定义marker&#xff0c;并且点击marker后弹出自定义的customCallout&#xff0c;并且customCallout的内容为用户点击marker的时候再从后台接口获取数据。 百度了一圈后发现居然没有一篇文章可以一次性完成&#xf…

使用opencv在图像上画带刻度线的十字线,以图像中心点为0点

使用OpenCV在图像上绘制带刻度线的十字线&#xff0c;可以通过以下步骤实现。我们将首先找到图像的中心点&#xff0c;然后绘制水平和垂直线&#xff0c;并在这些线的适当位置绘制刻度线。以下是详细的C代码示例&#xff1a; #include<opencv2\opencv.hpp> //画十字标注…

LeetCode题练习与总结:杨辉三角Ⅱ--119

一、题目描述 给定一个非负索引 rowIndex&#xff0c;返回「杨辉三角」的第 rowIndex 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 示例 1: 输入: rowIndex 3 输出: [1,3,3,1]示例 2: 输入: rowIndex 0 输出: [1]示例 3: 输入: rowIndex 1 输…

Spring Cloud工程添加子模块打包后文件为war包而非jar包

Spring Cloud工程添加子模块打包后文件为war包而非jar包 Spring Cloud子模块打出的包通常是JAR包而非WAR包&#xff0c;这是因为Spring Cloud主要基于Spring Boot构建&#xff0c;而Spring Boot默认打包为可执行JAR包。然而&#xff0c;如果遇到了Spring Cloud子模块打成了WAR…

前端 JS 经典:图片裁剪上传原理

前言&#xff1a;图片裁剪一般都是用户选择头像时用到&#xff0c;现在很多插件都可以满足这个功能&#xff0c;但是我们不仅要会用插件&#xff0c;还要自己懂的裁剪原理。 1. 流程 流程分为&#xff1a;1. 预览本地图片 2. 选择裁剪区域 3. 上传裁剪图像 2. 如何预览图片 …

08-指针与数组的结合——数组指针与指针数组的区别

指针与数组的结合 示例 1:指针访问数组元素 通过指针访问数组元素的例子&#xff1a; #include <stdio.h>int main() {int arr[5] {1,2,3,4,5};//int *p1 &arr;int *p1 (int *)&arr; // 需要强制类型转换int *p2 arr;printf("*p1:%d\n", *(p1 …

如何备份和恢复华为手机?

智能手机已成为我们日常生活中不可或缺的一部分&#xff0c;它们存储着大量敏感数据。因此&#xff0c;确保数据安全&#xff0c;定期备份至关重要&#xff0c;以防手机意外丢失、损坏或被盗。 如果您拥有华为设备&#xff0c;并且正在寻找如何将华为手机备份到PC的方法&#…