C++ 设计模式之策略模式

【声明】本题目来源于卡码网(题目页面 (kamacoder.com))

【提示:如果不想看文字介绍,可以直接跳转到C++编码部分】


【设计模式大纲】

【简介】什么是策略模式(第14种模式)

        策略模式是⼀种⾏为型设计模式,它定义了⼀系列算法(这些算法完成的是相同的⼯作,只是实现不同),并将每个算法封装起来,使它们可以相互替换,⽽且算法的变化不会影响使⽤算法的客户。
        举个例⼦,电商⽹站对于商品的折扣策略有不同的算法,⽐如新⽤户满减优惠,不同等级会员的打折情况不同,这种情况下会产⽣⼤量的if-else语句, 并且如果优惠政策修改时,还需要修改原来的代码,不符合开闭原则
        这就可以将不同的优惠算法封装成独⽴的类来避免⼤量的条件语句,如果新增优惠算法,可以添加新的策略类来实现,客户端在运⾏时选择不同的具体策略,⽽不必修改客户端代码改变优惠策略。


 【基本结构】

        策略模式包含下⾯⼏个结构:

  • 策略类Strategy : 定义所有⽀持的算法的公共接⼝。
  • 具体策略类ConcreteStrategy : 实现了策略接⼝,提供具体的算法实现。
  • 上下⽂类Context : 包含⼀个策略实例,并在需要时调⽤策略对象的⽅法。


 【简易实现】

        下面利用Java代码对策略模式的实现流程作以说明:

1. 抽象策略类

abstract class Strategy {// 抽象⽅法public abstract void algorithmInterface();
}

2. 具体策略类1

// 2. 具体策略类1
class ConcreteStrategyA extends Strategy {@Overridepublic void algorithmInterface() {System.out.println("Strategy A");// 具体的策略1执⾏逻辑}
}

3.具体策略类2

// 3. 具体策略类2
class ConcreteStrategyB extends Strategy {@Overridepublic void algorithmInterface() {System.out.println("Strategy B");// 具体的策略2执⾏逻辑}
}

4. 上下文类

// 4. 上下⽂类
class Context {private Strategy strategy;// 设置具体的策略public Context(Strategy strategy) {this.strategy = strategy;}// 执⾏策略public void contextInterface() {strategy.algorithmlnterface();}
}

5. 客户端代码

// 5. 客户端代码
public class Main{public static void main(String[] args) {// 创建上下⽂对象,并设置具体的策略Context contextA = new Context(new ConcreteStrategyA());// 执⾏策略contextA.contextInterface();Context contextB = new Context(new ConcreteStrategyB());contextB.contextInterface();u}
}

【使用场景】

        那什么时候可以考虑使⽤策略模式呢?

  • 当⼀个系统根据业务场景需要动态地在⼏种算法中选择⼀种时,可以使⽤策略模式。例如,根据⽤户的⾏为选择不同的计费策略。
  • 当代码中存在⼤量条件判断,条件判断的区别仅仅在于⾏为,也可以通过策略模式来消除这些条件语句。

        在已有的⼯具库中,Java 标准库中的 Comparator 接⼝就使⽤了策略模式,通过实现这个接⼝,可以创建不同的⽐较器(指定不同的排序策略)来满⾜不同的排序需求。


【编码部分】

1. 题目描述

        小明家的超市推出了不同的购物优惠策略,你可以根据自己的需求选择不同的优惠方式。其中,有两种主要的优惠策略: 

        1. 九折优惠策略:原价的90%。 

        2. 满减优惠策略:购物满一定金额时,可以享受相应的减免优惠。

具体的满减规则如下: 

        满100元减5元 

        满150元减15元 

        满200元减25元 

        满300元减40元

请你设计一个购物优惠系统,用户输入商品的原价和选择的优惠策略编号,系统输出计算后的价格。

2. 输入描述

        输入的第一行是一个整数 N(1 ≤ N ≤ 20),表示需要计算优惠的次数。 接下来的 N 行,每行输入两个整数,第一个整数M( 0 < M < 400) 表示商品的价格, 第二个整数表示优惠策略,1表示九折优惠策略,2表示满减优惠策略;

3. 输出描述

        每行输出一个数字,表示优惠后商品的价格;

4. C++ 编码实例

/**
* @version Copyright (c) 2024 NCDC, Servo。 Unpublished - All rights reserved
* @file StrategyMode.hpp
* @brief 策略模式
* @autor 写代码的小恐龙er
* @date 2024/01/16
*/#include <iostream>
#include <string>
#include <vector>using namespace std;// 前置声明// 优惠策略的抽象接口类
class AbstractStrategy;// 优惠策略的具体实现类1 -- 打 九折 
class StrategyNineDiscount;// 优惠策略的具体实现类2 -- 满减
class StrategyFullOut;// 上下文类 -- 调用优惠策略类
class DiscountContext;// 类的定义// 优惠策略的抽象接口类
class AbstractStrategy
{
// 接口函数
public:// 传入参数为 商品的原始价格 返回值为优惠后的价格virtual int ApplyDiscount(int originalPrice) = 0;
};// 优惠策略的具体实现类1 -- 打 九折 
class StrategyNineDiscount : public AbstractStrategy
{
// 成员函数
public:StrategyNineDiscount(){}// 重载 优惠函数int ApplyDiscount(int originalPrice) override {return (int) (originalPrice * 0.9);}
};// 优惠策略的具体实现类2 -- 满减
class StrategyFullOut : public AbstractStrategy
{
// 成员数据
private:int _prices[4] = {100, 150, 200, 300};int _discounts[4] = {5, 15, 25, 40};
// 成员函数
public:StrategyFullOut(){}// 重载 优惠函数int ApplyDiscount(int originalPrice) override { // 从最大的优惠开始判断int length = sizeof(_prices) / sizeof(_prices[0]);for(int i = length - 1; i >= 0; i--){if(originalPrice >= _prices[i]){return originalPrice - _discounts[i];}}// 未达到满减优惠区间 return originalPrice;}
};// 上下文类 -- 调用优惠策略类
class DiscountContext
{
// 成员数据
private:AbstractStrategy *_strategy;
// 成员函数
public://通过传入策略基类来构造该类的实例DiscountContext(AbstractStrategy *strategy){this->_strategy = strategy;}    // 管理优惠函数int ApplyDiscount(int originalPrice){ if(_strategy == nullptr) return 0;else return _strategy->ApplyDiscount(originalPrice);}
};int main()
{// 优惠次数int discountNum = 0;// 输入std::cin >> discountNum;// 构造上下文管理类DiscountContext *discountContext = nullptr;// 构造抽象策略类AbstractStrategy *strategy = nullptr;// 遍历输入所有的价格for(int i = 0; i < discountNum; i++){// 原始价格 和 优惠策略int originalPrice = 0;int discountType = 0;// 输入 std::cin >> originalPrice >> discountType;// 根据打折类型来操作if(discountType == 1){// 构造具体的优惠类strategy = new StrategyNineDiscount();}else if(discountType == 2){// 构造具体的优惠类strategy = new StrategyFullOut();}else std::cout << originalPrice << endl;discountContext = new DiscountContext(strategy);// 使用优惠函数originalPrice = discountContext->ApplyDiscount(originalPrice);std::cout<< originalPrice << endl;}// 析构if(strategy != nullptr){delete strategy;strategy = nullptr;}if(discountContext != nullptr){delete discountContext;discountContext = nullptr;}return 0;
}


......

To be continued.

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

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

相关文章

西门子WINCC常用C脚本1

1.置位&#xff0c;复位&#xff0c;取反 获取变量值&#xff1a;GetTagBit(可以是位也可以是字节&#xff0c;字&#xff0c;双字等具体字母不同) 设置变量值&#xff1a;SetTagBit 置位&#xff1a;SetTagBit&#xff08;"变量名",1&#xff09; 复位&#xff…

Node+Express编写接口---前端

前端页面 vue_node_admin: 第一个以node后端,vue为前端的后台管理项目https://gitee.com/ah-ah-bao/vue_node_admin.git

java-log4j日志冲突解决

一、概述 java日志框架较多&#xff0c;其中主流的slf4j和commons-logging是日志接口&#xff0c;log4j、log4j2和logback是真正的日志实现库。 二、具体库单独使用 2.1 log4j <dependency><groupId>log4j</groupId><artifactId>log4j</artifa…

Ceph分布式存储(1)

目录 一.ceph分布式存储 Ceph架构&#xff08;自上往下&#xff09; OSD的存储引擎&#xff1a; Ceph的存储过程&#xff1a; 二. 基于 ceph-deploy 部署 Ceph 集群 20-40节点上添加3块硬盘&#xff0c;一个网卡&#xff1a; 10节点为admin&#xff0c;20-40为node&…

指针理解C部分

目录 1.二级指针 2.指针数组 2.1指针数组的定义和表现形式 2.2指针数组模拟实现二维数组 2.2.1二维数组 2.2.2使用指针数组模拟实现二维数组 3.字符指针 2.数组指针 3.二维数组传参 4.函数指针 4.1函数指针变量的定义和创建 4.2函数指针变量的使用 4.3两段有趣的代码 4.…

Python自动化测试中APScheduler Flask的应用示例

使用背景 实际项目中&#xff0c;需要验证打点数据在各个系统中收集是否一致&#xff0c;而部分节点打点数据收集是通过异步任务实现的&#xff0c;等待时间比较久。为应对业务异步操作处理&#xff0c;实现异步数据的收集&#xff0c;经过调研后&#xff0c;选择了 APSchedule…

JMeter实操入门之登录

JMeter实操入门之登录 前言初级-无变量的登录线程组取样器-HTTP请求 进阶-定义变量的登录用户定义的变量获取JSON返回的数据-tokentoken设置全局变量 前言 安装及环境配置教程可移步&#xff1a;JMeter安装与配置环境 本篇文章针对小白进一步的认识及运用JMeter&#xff0c;围绕…

湖(岛屿)

from book&#xff1a;挑战程序设计竞赛

表的增删改查 进阶(二)

&#x1f3a5; 个人主页&#xff1a;Dikz12&#x1f525;个人专栏&#xff1a;MySql&#x1f4d5;格言&#xff1a;那些在暗处执拗生长的花&#xff0c;终有一日会馥郁传香欢迎大家&#x1f44d;点赞✍评论⭐收藏 目录 3.新增 4.查询 聚合查询 聚合函数 GROUP BY子句 HA…

shell编程学习

学习目标&#xff1a; 一周掌握 shell编程 变量的高级用法 变量替换 ##变量替换&#xff08;贪婪&#xff0c;从前往后匹配&#xff0c;匹配到进行删除&#xff09; test1I love you,you love me echo $test1 handletest1${test1##*ov} echo $handletest1##变量替换&#xff…

C#,入门教程(07)——软件项目的源文件与目录结构

上一篇&#xff1a; C#&#xff0c;入门教程(06)——解决方案资源管理器&#xff0c;代码文件与文件夹的管理工具https://blog.csdn.net/beijinghorn/article/details/124895033 创建新的 C# 项目后&#xff0c; Visual Studio 会自动创建一系列的目录与文件。 程序员后面的工…

使用 Kali Linux Hydra 工具进行攻击测试和警报生成

一、Hydra 工具和 Kali Linux 简介 在网络安全领域中&#xff0c;渗透测试是评估系统密码强度的重要组成部分。Hydra 是一款由黑客组织“The Hackers Choice”开发的开源登录破解工具&#xff0c;支持50多种协议。本教程将探索如何将 Hydra 与 Kali Linux 结合使用&#xff0c…

Android.mk和Android.bp的区别和转换详解

Android.mk和Android.bp的区别和转换详解 文章目录 Android.mk和Android.bp的区别和转换详解一、前言二、Android.mk和Android.bp的联系三、Android.mk和Android.bp的区别1、语法&#xff1a;2、灵活性&#xff1a;3、版本兼容性&#xff1a;4、向后兼容性&#xff1a;5、编译区…

新上线一个IT公司微信小程序

项目介绍 项目背景: 一家IT公司,业务包含以下六大块: 1、IT设备回收 2、IT设备租赁 3、IT设备销售 4、IT设备维修 5、IT外包 6、IT软件开发 通过小程序,提供在线下单,在线制单,在线销售,业务介绍,推广,会员 项目目的: 业务介绍: 包含企业业务介绍 客户需…

万字讲解新一代分布式任务调度框架Power-job

1、简介 Power-Job 的设计目标是成为企业级的分布式任务调度平台&#xff0c;整个公司统一部署调度中心 power-job-server&#xff0c;旗下所有业务线应用只需要依赖 power-job-worker 即可接入调度中心获取任务调度与分布式计算能力。 Power-job官方网址&#xff1a;http:/…

链动2+1模式:月流水6000万是怎么做到的?

一个好的企业往往只需要最简单的营销方式。当我们面对当今的商业市场&#xff0c;琳琅满目的商业模式&#xff0c;应接不暇的营销方案&#xff0c;我们一定会举足无措的不知道怎么选择。因为一个好的公司或企业&#xff0c;一定要有一个十分经得起推敲的模式来面对消费者。 那么…

失眠了,感谢技术人对“Spring Cloud Alibaba实战派的支持”

笔者从2015年开始接触Spring Boot&#xff0c;2017年开始接触Spring Cloud&#xff0c;到现在的Spring Cloud Alibaba已经整整快7个年头了&#xff0c;从2012年开始接触Java到现在已经整整10年了。 这里并没有倚老卖老的意思&#xff0c;只是想说作为一个纯碎的技术人&#xf…

Gin 框架之Cookie与Session

文章目录 一、Cookie和Session的由来二、Cookie简介1. 什么是Cookie2. Cookie规范3. 安全性4. Cookie 关键配置 三、Session简介1. 什么是Session2. Session 安全性3. 如何让客户端携带 sess_id 四、使用 Gin 的 Session 插件4.1 介绍4.2 基本使用 五、 session与store5.1 会话…

Win10 打开文件突然鼠标变成一个蓝色大圈卡住点不了也打不开文件,重启电脑也是这样

环境: Win10 专业版 加密客户端环境 问题描述: Win10 打开桌面word文件突然鼠标变成一个蓝色大圈卡住点不了也打不开文件,重启电脑也是这样,只有蓝色圈变大没有鼠标指针出现圈卡着不会动,和那些有鼠标箭头加小蓝色圈不一样 解决方案: 某网上查看的,还是要自己排查…

linux 更新镜像源

打开终端&#xff0c;备份一下旧的 源 文件&#xff0c;以防万一 cd /etc/apt/ ls sudo cp sources.list sources.list.bak ls然后打开清华大学开源软件镜像站 搜索一下你的linux发行版本&#xff0c;我这里是ubuntu发行版本 点击这个上面图中的问号 查看一下自己的版本号&a…