设计模式-策略(Strategy)模式

  • 又被称为政策(方针)模式
  • 策略模式(Strategy Design Pattern):封装可以互换的行为,并使用委托来决定要使用哪一个
  • 策略模式是一种行为设计模式,它能让你定义一系列算法,并将每种算法分别放入独立的类中,以使算法的对象能够相互替换
  • 用人话翻译后就是:运行时我给你这个类的方法传不同的 “key”,你这个方法就去执行不同的业务逻辑
  • 解释:
    • 现实世界例子:屠龙是一项危险的职业;有经验将会使它变得简单;经验丰富的屠龙者对不同类型的龙有不同的战斗策略
    • 直白点说,策略模式允许在运行时选择最匹配的算法
    • 在程序编程领域,策略模式(又叫政策模式)是一种启用在运行时选择算法的行为型软件设计模式
  • 仔细一想,这不就是 if else 干的事吗
  • 先直观的看下传统的多重 if else 代码:

  • 再来看策略模式类图:

  • 策略模式涉及到三个角色:
    • Strategy:策略接口或者策略抽象类,用来约束一系列的策略算法(Context 使用这个接口来调用具体的策略实现算法)
    • ConcreateStrategy:具体的策略类(实现策略接口或继承抽象策略类)
    • Context:上下文类,持有具体策略类的实例,并负责调用相关的算法
  • 先来看看最简单的策略模式 demo:
  • 1-策略接口(定义策略)

  • 2-具体的算法实现

  • 3-上下文的实现

  • 4-客户端使用(策略的使用)

  • 这种策略的使用方式其实很死板,真正使用的时候如果还这么写,和写一大推 if-else 没什么区别,所以我们一般会结合工厂类,在运行时动态确定使用哪种策略
  • 策略模式侧重如何选择策略、工厂模式侧重如何创建策略
  • 策略模式的功能就是把具体的算法实现从具体的业务处理中独立出来,把它们实现成单独的算法类,从而形成一系列算法,并让这些算法可以互相替换
  • 策略模式的重心不是如何来实现算法,而是如何组织、调用这些算法,从而让程序结构更灵活,具有更好的维护性和扩展性
  • 实际上,每个策略算法具体实现的功能,就是原来在 if-else 结构中的具体实现,每个 if-else 语句都是一个平等的功能结构,可以说是兄弟关系
  • 策略模式呢,就是把各个平等的具体实现封装到单独的策略实现类了,然后通过上下文与具体的策略类进行交互
  • 策略模式 = 实现策略接口(或抽象类)的每个策略类 + 上下文的逻辑分派

  • 策略模式的本质:分离算法,选择实现
  • 所以说,策略模式只是在代码结构上的一个调整,即使用了策略模式,该写的逻辑一个也少不了,到逻辑分派的时候,只是变相的 if-else
  • 而它的优化点是抽象了出了接口,将业务逻辑封装成一个一个的实现类,任意地替换
  • 在复杂场景(业务逻辑较多)时比直接 if-else 更好维护和扩展些
  • 在策略模式中,我们可以自己定义谁来选择具体的策略算法,有两种:
    • 客户端:当使用上下文时,由客户端选择,像我们上边的 demo
    • 上下文:客户端不用选,由上下文来选具体的策略算法,可以在构造器中指定
  • 避免冗长的if/else:
    • 比如在出门旅游时:路线、交通工具的类型、天数、舱位等级、餐饮、住宿等等
    • 每个节点在执行时,都需要根据预算进行不同的操作,从而引起大量的判断
    • 增加一个策略,修改一个策略,都有可能牵一发而动全身
    • 需要对所有状态进行回测

    • 整个业务如图所示,所有的判断都耦合在业务流程内部,牵一发而动全身

    • 使用策略模式
    • 我们可以将某一条件(Type)下的逻辑,聚合封装到具体的策略类中

    • 使用策略类后如图所示,每个的情况被封装聚合到单个策略类中,相互隔离

    • 所以策略模式的作用主要体现在:
      • 1-解耦策略的定义、创建和使用
      • 控制代码的复杂度,让每个部分都不至于过于复杂、代码量过多
      • 2-让复杂框架满足开闭原则
      • 添加或者修改新策略的时候,最小化、集中化代码改动,减少引入 bug 的风险
    • 策略的创建
    • 通常会通过类型(type)来判断创建哪个策略来使用
    • 这里,有两种创建方式
      • if-else创建
      • 适用于有状态的策略类,每次创建一个新的策略类给业务方使用

      • 通过工厂模式里的Map进行创建
      • 适用于无状态的策略类创建,大家共用一个策略类即可

      • 本质上讲,是借助“查表法”,根据 type 查表替代根据 type 分支判断
  • Java中的例子:
    • 采用 Comparator 参数的 Collections.sort() 方法;根据 Comparator 接口的不同实现,对象会以不同的方式进行排序
  • 使用策略模式应当:
    • 许多相关的类只是行为不同;策略模式提供了一种为一种类配置多种行为的能力
    • 你需要一种算法的不同变体;比如,你可能定义反应不用时间空间权衡的算法;当这些算法的变体使用类的层次结构来实现时就可以使用策略模式
    • 一个算法使用的数据客户不应该对其知晓;使用策略模式来避免暴露复杂的,特定于算法的数据结构
    • 一个类定义了许多行为,这些行为在其操作中展现为多个条件语句;移动相关的条件分支到它们分别的策略类中来代替这些条件语句

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

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

相关文章

每天五分钟计算机视觉:Inception网络是由多个Inception模块构成

本文重点 inception从另一种角度来提升训练结果:能更高效的利用计算资源,在相同的计算量下能提取到更多的特征,从而提升训练结果。可以简单的理解为Inception 网络是由一个一个的Inception模块构建成的,我们来看一下。 Inception模块 如上就是Inception模块的 通过一个1…

Linux-----12、时间日期

# 时间日期 # 时区设置 在Linux (opens new window)系统中,默认使用的是UTC时间。 即使在安装系统的时候,选择的时区是亚洲上海,Linux默认的BIOS时间(也称:硬件时间)也是UTC时间 (opens new window)。 在…

逻辑回归代价函数

逻辑回归的代价函数通常使用交叉熵损失来定义。这种损失函数非常适合于二元分类问题。 本篇来推导一下逻辑回归的代价函数。 首先,我们在之前了解了逻辑回归的定义:逻辑回归模型是一种用于二元分类的模型,其预测值是一个介于0和1之间的概率…

这种形状的土堆,用DasViewer土方计算时该选择哪种模式?

答:推荐拟合平面;当堆料的整个边界可见并且基面是具有相同高度的坚硬表面、斜坡或平坦时,推荐该选项。 DasViewer是由大势智慧自主研发的免费的实景三维模型浏览器,采用多细节层次模型逐步自适应加载技术,让用户在极低的电脑配置下,也能流畅…

nginx 1.24.0 安装nginx最新稳定版

1.官网: nginx: download 2. 选择稳定版: 3. 可以下载,然后上传服务器,也可以wget获取: cd /home wget https://nginx.p2hp.com/download/nginx-1.24.0.tar.gz 4. 放入/home 下。并解压缩,重命名nginx;…

Tomcat性能优化

Tomcat是一款常用的Java Web应用服务器,对其进行性能优化可以提高Web应用的响应速度和吞吐量。Tomcat性能取决于内存的大小。 增加JVM内存:在Tomcat的bin目录下的catalina.sh文件中修改JAVA_OPTS参数,将堆内存大小-Xmx和-Xms调整为适当的值。…

Leetcode 剑指 Offer II 057. 存在重复元素 III

题目难度: 中等 原题链接 今天继续更新 Leetcode 的剑指 Offer(专项突击版)系列, 大家在公众号 算法精选 里回复 剑指offer2 就能看到该系列当前连载的所有文章了, 记得关注哦~ 题目描述 给你一个整数数组 nums 和两个整数 k 和 t 。请你判断是否存在 两…

Centos开机进入grub命令行模式进入不了操作系统

环境:没有linux命令,没有initrd命令,没有init6命令 由于删除了/boot/efi/EFI/centos/grub.cfg ,重启服务器后,无法进入原来正常的系统,进入了grub命令行界面 备注:对于centos7/8/openEuler: 如果…

我的NPI项目之Android 安全系列 -- EMVCo

最近一直在和支付有关的内容纠缠,原来我负责的产品后面还要过EMVCo的认证。于是,就网上到处找找啥事EMVCo,啥是EMVCo,啥是EMVCo。 于是找到了一个神奇的个人网站:Ganeshji Marwaha 虽然时间有点久远,但是用…

聚观早报 |红魔9 Pro氘锋透明银翼版开售;荣耀90 GT将发布

【聚观365】12月16日消息 红魔9 Pro氘锋透明银翼版开售 荣耀90 GT将发布 德国成功化解预算僵局 第二届起点读书“网文填坑节”收官 阿维塔科技拟 2025 年赴港上市 红魔9 Pro氘锋透明银翼版开售 现在有最新消息,近日红魔9 Pro氘锋透明银翼版本开启全款预售&…

风速预测(五)基于Pytorch的EMD-CNN-LSTM模型

目录 前言 1 风速数据EMD分解与可视化 1.1 导入数据 1.2 EMD分解 2 数据集制作与预处理 2.1 先划分数据集,按照8:2划分训练集和测试集 2.2 设置滑动窗口大小为96,制作数据集 3 基于Pytorch的EMD-CNN-LSTM模型预测 3.1 数据加载&…

Android 12.0 Launcher3定制化之动态时钟图标功能实现

1.概述 在12.0的系统产品rom定制化开发中,在Launcher3中的定制化的一些功能中,对于一些产品要求需要实现动态时钟图标功能,这就需要先绘制时分秒时针表盘,然后 每秒刷新一次时钟图标,时钟需要做到实时更新,做到动态时钟的效果,接下来就来分析这个功能的实现 如图: 2.动…