设计模式--策略模式

2023-11-07

策略(Strategy)模式

本质:分离算法,选择实现。

策略模式:针对一组算法,将每一个算法封装到具有共同接口的独立的类中,使得它们可以互换。

使用策略模式可以把行为和环境分割开来。环境类Context负责查询要做什么,各种算法则在具体策略类(ConcreteStrategy)中提供。

当出现新的促销折扣或现有的折扣政策出现变化时,只需要实现新的策略类,并在客户端登记即可。

在这里插入图片描述

环境(Context):有一个Strategy类的引用,和具体的策略类交互。
抽象策略(Strategy)角色:一个接口或抽象类,给出规范。
具体策略(ConcreteStrategy)角色:具体算法或行为。

上下文使用具体策略对象,具体策略对象也可以从上下文获取所需要的数据,因此,可以将上下文当做参数传递给具体策略对象。

上下文封装着具体策略对象需要的数据,具体策略对象通过回调上下文的方法来获取这些数据。

这里为了方便理解,我们就拿刚学习Java的时候使用计算方法来说吧。
在使用计算器进行计算的时候,会经常用到加减乘除方法。如果我们想得到两个数字相加的和,我们需要用到“+”符号,得到相减的差,需要用到“-”符号等等。虽然我们可以通过字符串比较使用if/else写成通用方法,但是计算的符号每次增加,我们就不得不加在原先的方法中进行增加相应的代码,如果后续计算方法增加、修改或删除,那么会使后续的维护变得困难。
但是在这些方法中,我们发现其基本方法是固定的,这时我们就可以通过策略模式来进行开发,可以有效避免通过if/else来进行判断,即使后续增加其他的计算规则也可灵活进行调整。

策略模式的收银软件

抽象类CashStrategy:定义收银的计算方法

CashContext角色:引用CashStrategy的一个实例

CashNormal是正常收费,CashRebate是打折收费,CashReturn是返利收费,是三个具体策略,客户端判断决定选择使用哪一个。

public abstract class CashStrategy {
	
	public abstract double acceptCash(double money);

}
public class CashContext {
	private CashStrategy cs;

	public CashContext(CashStrategy cs) {
		this.cs = cs;
	}
	
	public double getResult(double money) {
		return cs.acceptCash(money);
	}

}

public class CashNormal extends CashStrategy{

	@Override
	public double acceptCash(double money) {
		// TODO Auto-generated method stub
		return money;
	}
	
}
public class CashRebate extends CashStrategy{
	private double moneyRebate=0;
	
	public CashRebate(double moneyRebate) {
		this.moneyRebate = moneyRebate;
	}

	@Override
	public double acceptCash(double money) {
		return money*moneyRebate;
	}
	
}
public class CashRetrun extends CashStrategy{

	private double moneyCondition=0.0;
	private double moneyReturn=0.0;
	
	
	public CashRetrun(double moneyCondition, double moneyReturn) {
		this.moneyCondition = moneyCondition;
		this.moneyReturn = moneyReturn;
	}

	@Override
	public double acceptCash(double money) {
		double result=money;
		if(money>moneyCondition)
			result=money-Math.floor(money/moneyCondition)*moneyReturn;
			//floor():向下取整
		return result;
	}

}
import java.util.Scanner;

public class Test {
	
	static double total=0.0;
	public static void main(String[] args) {
		Scanner cin=new Scanner(System.in);
		System.out.println("请输入优惠方案:");
		String str=cin.next();
		CashContext cc=null;
		
		switch(str) {
		case "正常收费":
			cc=new CashContext(new CashNormal());
			break;
		case "满300返100":
			cc=new CashContext(new CashRetrun(300,100));
			break;
		case "打8折":
			cc=new CashContext(new CashRebate(0.8));
			break;
		}
		
		System.out.println("请输入消费金额:");
		double price=cin.nextInt();
		total=cc.getResult(price);
		
		System.out.println("最后共消费:"+total);
		cin.close();
	}

}

策略模式的特点

  • 功能:具体算法从具体业务处理中独立
  • 多个if-else出现考虑使用策略模式
  • 策略算法是形同行为的不同实现(多态)
  • 客户端选择,上下文来具体实现策略算法

使用场景

同一个算法,有很多不同的实现情况。

一个定义了很多行为的类,通过多个if-else语句来选择这些行为的情况

优缺点

优点:

  • 避免让客户端涉及到重要算法和数据
  • 避免使用难以维护的多重条件选择语句
  • 易扩展

缺点:

  • 判断逻辑在客户端,需求改变时,要更改客户端的程序。
  • 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。
  • 增加了对象的数目
  • 只适合扁平的算法结构

策略模式和工厂模式的结合

把分支判断从客户端移动到到环境CashContext类中,此时CashContext相当于一个工厂,选择实例化不同的具体策略类

public class CashContext {
	private CashStrategy cs=null;
	
	//简单工厂:将实例化具体策略从客户端放入Context类中
	public CashContext(String type) {
		switch(type) {
		case "正常收费":
			CashNormal cs0=new CashNormal();
			cs=cs0;
			break;
		case "满300返100":
			CashRetrun cr1=new CashRetrun(300,100);
			cs=cr1;
			break;
		case "打8折":
			CashRebate cr2=new CashRebate(0.8);
			cs=cr2;
			break;
		}
		
	}
	
	public double getResult(double money) {
		return cs.acceptCash(money);
	}

}

import java.util.Scanner;

public class Test {

	public static void main(String[] args) {
		Scanner cin=new Scanner(System.in);
		
		System.out.println("请输入优惠方案:");
		String str=cin.next();
		CashContext cc=new CashContext(str);
		
		System.out.println("请输入消费金额:");
		double price=cin.nextInt();
		double total=cc.getResult(price);
		
		System.out.println("最终消费:"+total);
		cin.close();
	}

}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

设计模式--策略模式 的相关文章

  • Rider 使用

    下载地址 http www jetbrains com rider fromMenu 破解 https www iteblog com archives 1542 html http idea iteblog com key php 使用

随机推荐

  • 约瑟夫环问题(单循环链表实现)

    用单循环链表解决约瑟夫环问题 大致思路 1 利用尾插法建立一个循环链表 建表成功后删除头结点 2 核心算法 生成一个work指针 每走到约定的step 1的位置时停止 利用pdel指针标记后继结点 循环释放pdel 直到work work
  • java数组(二)

    数组 Arrays 数组是一种数据结构 它是一组相同类型的元素的集合 该集合中的每个元素都通过一个索引访问 在Java中 数组是一个对象 它可以存储在堆上或栈上 具体取决于它如何创建 数组可以是单维数组或多维数组 数组是一个固定长度的数据结
  • C++(基础入门笔记)

    1搭建环境 include
  • TCP/IP/UDP/RTP/RTCP协议

    IP 指定目的地址和源地址 Version 版本号 四个字节 IHL IP Header Length IP头长度 Total Length 总的长度 总的长度减去IP头长度 数据长度 Identification Flags Fragme
  • linux OSI七层模型、TCP/IP协议栈及每层结构大揭秘

    学习Linux 就算是像小编我这样的小萌新 也知道OSI模型 什么 你不知道 好吧 这篇秘籍拿走 不谢 一 两个协议 1 OSI 协议模型 7层 国际协议 PDU 协议数据单元对等层次之间传递的数据单位 OSI协议 7层 国际协议 PDU
  • 伺服控制-canopen

    通迅中断参数设 1 中断 停止 伺服驱动 电机停转 开启抱死动作 1 配置 opration 2 设置 3速度模式 3 设置 伺服松轴 4 设置 伺服使能 运行 1 使能 true 2 启用 true 停止 1 使能 false 2 松轴
  • Linux下安装Nginx服务并设置开机自启动

    目录 一 安装Nginx 二 开机自启动服务配置 一 安装Nginx 系统平台 CentOS Linux release 7 9 2009 Core 64位 Nginx安装版本 liunx 64位 nginx 1 20 2 tar gz 安
  • VSCode进行Lua调试

    1 安装EmmyLua 2 添加配置 3 开始调试 要选择要调试的进程就可以了
  • Docker中快速搭建SFTP

    1 拉docker镜像 docker pull atmoz sftp 2 初始化 创建容器 docker run name internalsftp p 22 22 d atmoz sftp anonymous hello123 opt U
  • 震惊~Signal <XXX> missing in the sensitivity list is added for synthesis purposes在verilog中警告的解决方法

    你是否还在为秃头而烦恼 你是否还在通宵为了赶项目而焦急 朋友 你不是 一个人 看看吧 下面是这个bug的描述 WARNING HDLCompiler 91 F FPGA Doc AD test uart v Line 56 Signal
  • java通过JDBC连接mysql8.0数据库,并对数据库中的表进行增删改查操作

    目录 一 JDBC简介 二 添加依赖 三 JDBC操作数据库的步骤 四 JDBC操作数据库 增删改查 一 新增数据 二 删除数据 三 修改数据 四 查询数据 五 多表连接查询 一 JDBC简介 Java数据库连接 Java Database
  • vue-cli配置sass,使用全局sass变量

    vue cli创建vue2 0项目 安装sass步骤 创建vue2 0项目 vue init webpack 项目名 安装sass步骤 npm install node sass 4 14 1 npm install sass loader
  • JMP、Hook

    include stdio h include tchar h include windows h offset 目标地址 jmp指令起始地址 5 跳转指令解码 0xe9 offset offset 有符号整型 四字节 它等于jmp指令的下
  • 微信小程序——仿盒马鲜生APP

    前段时间 随着马化腾现身全国多地用微信小程序乘坐公交的新闻出现 微信小程序的热度可谓是更上了一层 微信小程序现身至今 因其不用下载就可使用的方便等优点 发展趋势一直良好 盒马鲜生的问世也是充满了热度 实现了快速配送 可谓是阿里巴巴对线下超市
  • 科幻风的卡片视频播放

    上一篇博文展示了卡片中的VR展示 那篇主要是卡片的3D转动来展示未显示的部分图片 这篇 我们来点科幻的 我们在卡片中播放视频的同时来拖动卡片或转动它 像下面那样 这个主要依赖了两个库 具体代码如下
  • 浅谈js宏观任务、微观任务

    js运行机制分为同步异步 异步又分为宏观事件和微观事件 同步异步 js是一门单线程语言 因此js在同一个时间里只能做一件事 单线程意味着 如果在同个时间有多个任务的话 这些任务就需要排队 前一个执行完成才能执行下一个任务 同步任务 同步任务
  • Echarts:象形柱图实现水塔水位的动画、水球图和液位柱子图

    一 象形柱图 1 vue中使用象形柱图 效果图 2 代码实现
  • axios调接口 与缓存

    axios getarr1 let url https www fastmock site mock f5427ab2a4d20236b4aed7a0579d2213 api shop list 调接口 后端给的地址 this axios
  • 【React】手把手学习React - 元素渲染

    前言 大家好 分享了这么多文章发现无论是项目实战还是源码分析或者是基本使用 绝大多数文章都是关于Vue的 还没有关于React的分享 接下来从今天开始我们将一起学习一下React React与vue一样也是一个非常火爆的前端库 关于Reac
  • 设计模式--策略模式

    文章目录 策略 Strategy 模式 策略模式的收银软件 策略模式的特点 使用场景 优缺点 策略模式和工厂模式的结合 策略 Strategy 模式 本质 分离算法 选择实现 策略模式 针对一组算法 将每一个算法封装到具有共同接口的独立的类