策略(政策)模式

news/2024/10/22 4:23:48/

简介

策略模式(Strategy Pattern)又叫作政策模式(Policy Pattern),它将定义的算法家族分别封装起来,让它们之间可以互相替换,从而让算法的变化不会影响到使用算法的用户,属于行为型设计模式。

通用模板

  1. 创建抽象策略角色:规定策略或算法的行为。

    // 策略接口
    public interface IStrategy {void algorithm();
    }
    
  2. 创建具体策略角色:具体的策略或算法实现。

    // 具体策略类A
    public class ConcreteStrategyA implements IStrategy{@Overridepublic void algorithm() {System.out.println("ConcreteStrategyA");}
    }
    
    // 具体策略类B
    public class ConcreteStrategyB implements IStrategy {@Overridepublic void algorithm() {System.out.println("ConcreteStrategyB");}
    }
    
  3. 上下文角色:用来操作策略的上下文环境,屏蔽高层模块(客户端)对策略、算法的直接访问,封装可能存在的变化。

    // 操作策略的上下文
    public class Context {private IStrategy strategy;public Context(IStrategy strategy) {this.strategy = strategy;}public void algorithm() {this.strategy.algorithm();}
    }
    

模板测试

  1. 测试代码

    public class Client {public static void main(String[] args) {// 选择一个具体策略IStrategy strategy = new ConcreteStrategyA();// 创建一个上下文环境Context context = new Context(strategy);// 客户端直接让上下文角色执行算法context.algorithm();}
    }
    
  2. 结果

    ConcreteStrategyA
    

应用场景

策略模式在生活场景中的应用非常多。比如,一个人的纳税比率与他的工资有关,不同的工资水平对应不同的税率。再比如,在互联网移动支付的大背景下,我们每次下单后付款前,都需要选择支付方式。

策略模式可以解决在有多种相似算法的情况下使用if…else或switch…case所带来的复杂性和臃肿性问题。在日常业务开发中,策略模式适用于以下应用场景。
(1)针对同一类型问题,有多种处理方式,每一种都能独立解决问题。
(2)需要自由切换算法的场景。
(3)需要屏蔽算法规则的场景。

优点

(1)策略模式符合开闭原则。
(2)避免使用多重条件转移语句,如if…else语句、switch…case语句
(3)使用策略模式可以提高算法的保密性和安全性。

缺点

(1)客户端必须知道所有的策略,并且自行决定使用哪一个策略类。
(2)代码中会产生非常多策略类,增加维护难度。

“生搬硬套”实战

场景描述

假设你是一名餐厅经理,餐厅提供多种优惠活动来吸引顾客。优惠活动包括打折、满减、买一送一等。每种优惠活动都有不同的计算方式,但餐厅的收银系统需要能够灵活地应用这些优惠活动。

代码开发
  1. 创建抽象策略角色(这里指打折策略接口)

    // 打折策略接口
    public interface IDiscountStrategy {double applyDiscount(double originalPrice);
    }
    
  2. 创建具体策略角色(这里指百分比打折策略、固定金额减免策略、买一送一策略)

    // 根据折扣百分比计算最终价格
    public class PercentageDiscount implements IDiscountStrategy {private double discountPercentage;public PercentageDiscount(double discountPercentage) {this.discountPercentage = discountPercentage;}@Overridepublic double applyDiscount(double originalPrice) {return originalPrice * (1 - discountPercentage / 100);}
    }
    
    // 根据固定金额减免计算最终价格
    public class FixedAmountDiscount implements IDiscountStrategy {private double discountAmount;public FixedAmountDiscount(double discountAmount) {this.discountAmount = discountAmount;}@Overridepublic double applyDiscount(double originalPrice) {return Math.max(originalPrice - discountAmount, 0); // 确保折扣后价格不低于0}
    }
    
    // 买一送一策略,计算最终价格为原价的一半
    public class BuyOneGetOneFree implements IDiscountStrategy {@Overridepublic double applyDiscount(double originalPrice) {return originalPrice / 2; // 买一送一,相当于半价}
    }
    
  3. 创建上下文(这里就是收银系统)

    // 用来操作策略的上下文,这里就是收银系统
    public class Cashier {private IDiscountStrategy strategy;public Cashier(IDiscountStrategy strategy) {this.strategy = strategy;}public double calculateFinalPrice(double originalPrice) {return strategy.applyDiscount(originalPrice);}
    }
    

至此,我们就通过“生搬硬套”策略模式的模板设计出一套上下文可以灵活选择不同策略算法的系统,接下来我们进行测试:

  • 测试代码
    public class Client {public static void main(String[] args) {// 折扣百分比策略IDiscountStrategy percentageDiscount = new PercentageDiscount(10);Cashier cashierWithPercentageDiscount = new Cashier(percentageDiscount);double finalPriceWithPercentage = cashierWithPercentageDiscount.calculateFinalPrice(100);System.out.println("Final price with percentage discount: " + finalPriceWithPercentage);// 固定金额减免策略IDiscountStrategy fixedAmountDiscount = new FixedAmountDiscount(20);Cashier cashierWithFixedAmountDiscount = new Cashier(fixedAmountDiscount);double finalPriceWithFixedAmount = cashierWithFixedAmountDiscount.calculateFinalPrice(100);System.out.println("Final price with fixed amount discount: " + finalPriceWithFixedAmount);// 买一送一策略IDiscountStrategy buyOneGetOneFree = new BuyOneGetOneFree();Cashier cashierWithBuyOneGetOneFree = new Cashier(buyOneGetOneFree);double finalPriceWithBuyOneGetOneFree = cashierWithBuyOneGetOneFree.calculateFinalPrice(100);System.out.println("Final price with buy one get one free: " + finalPriceWithBuyOneGetOneFree);}
    }
    
  1. 结果
    Final price with percentage discount: 90.0
    Final price with fixed amount discount: 80.0
    Final price with buy one get one free: 50.0
    

总结

策略是指,定义一组算法,并把其封装到一个对象中。然后在运行时,可以灵活的使用其中的一个算法。这种模式非常适合那些需要根据不同情况选择不同行为的场景。


http://www.ppmy.cn/news/1532755.html

相关文章

22.4k star,好用、强大的链路监控软件,skywalking

skywalking其实用的比较少,但其实目前持续更新下,功能还是蛮强大的,目前支持的agent也是蛮多的,如下是一些常规的支持agent,如果在选择链路监控的话,可以看下这款。 当谈到应用性能监控(Applica…

Docker精讲:基本安装,简单命令及核心概念

docker服务部署 docker是一个容器管理工具,其内部容器才是具体服务,所以我们在安装docker时不需要有太多定制内容,只需要通过yum安装即可 1. 更新系统包 #更新现有依赖包,防止现有依赖包版本过低影响docker安装 yum update2. 安…

docker简介、安装、基础知识

基础知识 Docker简介: 1.Docker是一种用于构建、发布及运行应用程序的开源项目,他通过容器化技术简化了应用程序的部署和管理 2.Docker是一个开源的应用容器引擎,基于go语言开发,为应用打包、部署平台,而非单纯的虚…

Mac安装Manim并运行

1.在macOS上创建Python虚拟环境,可以使用venv模块,这是Python自带的库,也可以使用conda。以下是使用venv创建和使用Python虚拟环境的步骤: 打开终端。 创建一个新的目录来存放你的项目,并进入该目录: mk…

【解决】Mac 上 M系列芯片用 Vmware Fusion安装 win11 遇到的主要的问题汇总

此文很短,没闲话,干活满满 Mac 版本最干净版本的 win11 免费下载链接 :链接:https://pan.quark.cn/s/4e8e8bb93564 本文实验电脑为:Macbook Air M3 第一个问题:如何解决安装Windows11时出现“这台电脑无…

YOLOv5改进:Shuffle Attention注意力机制【注意力系列篇】(附详细的修改步骤,以及代码)

如果实验环境尚未搭建成功,可以参考这篇文章 ->【YOLOv5超详细环境搭建以及模型训练(GPU版本)】 文章链接为:http://t.csdnimg.cn/Ke0bb ---------------------------------------------------------------------------​ 1…

数据结构之链表(2),双向链表

目录 前言 一、链表的分类详细 二、双向链表 三、双向链表的实现 四、List.c文件的完整代码 五、使用演示 总结 前言 接着上一篇单链表来详细说说链表中什么是带头和不带头,“哨兵位”是什么,什么是单向什么是双向,什么是循环和不循环。然后实…

【Linux篇】网络编程——I/O复用

目录 一、初识复用 1. 认识复用 2. 复用的优点 3. 复用技术在服务端的应用 二、select 技术 1. 设置文件描述符(fd_set) 2. 文件描述符的控制 (1)FD_ZERO (2)FD_SET (3)FD…