设计模式,策略模式

策略模式概述

策略模式,即与解决问题的策略有关的模式,该模式旨在更好的实现策略的实现。策略模式分为三个部分:环境、抽象策略角色、具体策略角色。策略模式能使得更好地管理和使用一类算法。

  • 环境(context):用于确定对应的具体策略角色。并将解决策略的功能最终放在环境context中(只要向下调用功能即可)。
  • 抽象策略角色:能完成一种问题的解决的各种算法的范称,通常为接口,定义能解决问题的功能,但是不实现,具体的算法的步骤由实现类解决。
  • 具体策略角色:实现抽象策略角色,要完成具体的解决问题的功能的角色。

代码实现举例

如果一家商场能让顾客办会员卡以达到优惠的目的,而会员卡分为两种:八折卡、满减卡(没满三百减五十)。要求输入原价格和优惠方式,得到优惠后的价格。

分析,这里的抽象策略角色应该为优惠方式,而具体策略角色有三个:八折、满减、普通,而环境(通常用context表示)用于确定对应具体的优惠方式

抽象策略角色(优惠方式)

/*** 表示优惠的算法,具体优惠方式由实现类定义*/
public interface Concession {//计算优惠后的价格的功能Double doConcession(Double price);
}

具体策略角色(优惠方式的不同具体实现)

普通:

/*** 没有优惠卡的计算方法*/
public class NormalConcession implements Concession {@Overridepublic Double doConcession(Double price) {return price;}
}

八折卡:

/***  有八折卡的计算方法*/
public class RebateConcession implements Concession {@Overridepublic Double doConcession(Double price) {return price * 0.8;}
}

满减卡:

/*** 有满减卡的计算方法(每满三百减五十)*/
public class ReturnConcession implements Concession {@Overridepublic Double doConcession(Double price) {return price - ( (int)(price / 300) * 50 );}
}

普通策略模式的环境(context)

/*** 普通策略模式的Context类,用于决定不同的算法*/
public class ConcessionContext {private Concession concession;public ConcessionContext(Concession concession){this.concession = concession;}public Double doConcession(Double price){return concession.doConcession(price);}
}

通过传入不同的具体策略模式的对象,来决定其成员变量concession是怎样的策略。并且将策略的功能最终放在环境中,业务代码只要调用环境的功能的方法即可。

主要业务代码

public class Main {public static void main(String[] args) throws Exception {Scanner scan = new Scanner(System.in);System.out.println("请输入原价格");double price = scan.nextDouble();System.out.println("请输入优惠方式");String method = scan.next();ConcessionContext context = null;switch (method){case "普通":context = new ConcessionContext(new NormalConcession());break;case "八折卡":context = new ConcessionContext(new RebateConcession());break;case "满减卡":context = new ConcessionContext(new ReturnConcession());break;default:context = null;break;}if (context == null){throw new Exception("方式错误");}Double concession = context.doConcession(price);System.out.println("优惠后价格为:" + concession);}

但是这种方式有一些缺点:

  • 具体策略的选择在业务代码中进行,当修改底层时(比如增加、删除、更新了策略)也要修改业务代码
  • 业务代码中要实例化各种具体策略对象,使得代码繁杂,而且个人感觉这样使得环境context有点多余,在这种情况下,context只是起了一个没有中间作用的类,判断完后直接使用具体实现策略的对象调用方法差别也不大

策略模式与简单工厂模式相结合

结合的要点是,让环境context起到一个工厂类的效果,来完成实例化。并且,让context去完成具体实现策略的判断后再作对应,我们只要传入要选择的策略的标识即可(比如传入目标策略的名字,让context根据此名字来实例化对应的策略对象)。

升级版的context

/*** 策略者模式与简单工厂模式相结合*/
public class ConcessionContextPlus {Concession context = null;public ConcessionContextPlus(String method) throws Exception {switch (method){case "普通":context = new NormalConcession();break;case "八折卡":context = new RebateConcession();break;case "满减卡":context = new ReturnConcession();break;default:context = null;break;}if (context == null) {throw new Exception("方式错误");}}public Double doConcession(Double price){return context.doConcession(price);}
}

升级后的业务代码

/*** 升级版业务(非常简洁,可读性高)*/
public class MainPlus {public static void main(String[] args) throws Exception {Scanner scan = new Scanner(System.in);System.out.println("请输入原价格");double price = scan.nextDouble();System.out.println("请输入优惠方式");String method = scan.next();//实际上两步就完成了策略//传入优惠方式ConcessionContextPlus concessionContextPlus = new ConcessionContextPlus(method);//传入原价格Double concession = concessionContextPlus.doConcession(price);System.out.println("优惠后价格为" + concession);}
}

升级后的业务代码明显简单了很多。

总结

  • 策略模式能更好地管理和使用一类算法,在做算法增删改时,无需改动业务代码,只要对底层进行修改。使得代码的耦合度低,封装性强。
  • 策略模式结合简单工厂模式,让context起到工厂的作用,能让业务代码更为简洁,也更易于理解和使用。比起普通的策略模式,耦合度更低,封装性更强。

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

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

相关文章

【状态估计】概率论基础

《机器人学的状态估计》是入行SLAM的经典书籍之一,其中有大量的公式相关的内容,看起来还是比较艰涩的。最近重新读一遍,顺便将其中的一些内容记录下来,方便以后回看。 概率密度函数 定义 定义 x x x为区间 [ a . b ] [a.b] [a.b…

牛客NC108 最大正方形【中等 动态规划 Java,Go,PHP】

题目 题目链接: https://www.nowcoder.com/practice/0058c4092cec44c2975e38223f10470e 思路 动态规划: 先初始化第一行和第一列。然后其他单元格依赖自己的上边,左边和左上角参考答案Java import java.util.*;public class Solution {/*** 代码中的类…

智能新纪元:AI大模型学习的奥秘与挑战

在当前技术环境下,AI大模型学习不仅要求研究者具备深厚的数学基础和编程能力,还需要对特定领域的业务场景有深入的了解。通过不断优化模型结构和算法,AI大模型学习能够不断提升模型的准确性和效率,为人类生活和工作带来更多便利。…

Naive UI:一个 Vue 3 组件库,比较完整,主题可调,使用 TypeScript,快有点意思。

在当今的前端开发领域,Vue 3已成为中后台应用的首选框架。为了满足开发者的需求,各种组件库如雨后春笋般涌现。其中,Naive UI以其独特的优势,成为了Vue 3开发者的得力助手。本文将深入探讨Naive UI的特性、优势以及如何使用它来提…

浏览器强缓存和弱缓存的主要区别

浏览器强缓存与弱缓存 浏览器的缓存机制主要分为两种:强缓存与协商缓存(也称弱缓存)。 强缓存 强缓存是指浏览器在请求一个资源时,不与服务器发生通信,直接从本地缓存中获取资源。如果存在有效的强缓存,…

docker镜像安装空间不足no space left on device

报错:Error processing tar file(exit status 1): open /usr/local/lib/libmkl_tbb_thread.so.1: no space left on device 原先docker模型保存位置: docker info -f ‘{{ .DockerRootDir}}’ docker 高点版本,这里26.0 解决参考&#xf…

学习次模函数-第1章 引言

许多组合优化问题可以被转换为集合函数的最小化,集合函数是在给定基集合的子集的集合上定义的函数。同样地,它们可以被定义为超立方体的顶点上的函数,即,其中是基集合的基数-它们通常被称为伪布尔函数[27]。在这些集合函数中&…

Linux 创建交换空间

🚀 作者主页: 有来技术 🔥 开源项目: youlai-mall 🍃 vue3-element-admin 🍃 youlai-boot 🌺 仓库主页: Gitee 💫 Github 💫 GitCode 💖 欢迎点赞…

P1012 [NOIP1998 提高组] 拼数 排序

[NOIP1998 提高组] 拼数 题目描述 设有 n n n 个正整数 a 1 … a n a_1 \dots a_n a1​…an​,将它们联接成一排,相邻数字首尾相接,组成一个最大的整数。 输入格式 第一行有一个整数,表示数字个数 n n n。 第二行有 n n …

鸿蒙Harmony应用开发—ArkTS-应用级变量的状态管理

状态管理模块提供了应用程序的数据存储能力、持久化数据管理能力、UIAbility数据存储能力和应用程序需要的环境状态。 说明: 本模块首批接口从API version 7开始支持,后续版本的新增接口,采用上角标单独标记接口的起始版本。 本文中T和S的含义…

“文本魔术师:Python玩转文字格式转换“

Hey小伙伴们,今天我们要一起探索一个超级实用的小技能——Python文字转换器!想象一下,你的文字作品能瞬间变换成小说、诗歌、甚至是密码,是不是很酷?跟着我,咱们一步步来学习如何用Python实现这个神奇的功能…

赋能数据收集:从机票网站提取特价优惠的JavaScript技巧

背景介绍 在这个信息时代,数据的收集和分析对于旅游行业至关重要。在竞争激烈的市场中,实时获取最新的机票特价信息能够为旅行者和旅游企业带来巨大的优势。 随着机票价格的频繁波动,以及航空公司和旅行网站不断推出的限时特价优惠&#xff…

【洛谷 P2347】[NOIP1996 提高组] 砝码称重 题解(动态规划+01背包+位集合)

[NOIP1996 提高组] 砝码称重 题目描述 设有 1 g 1\mathrm{g} 1g、 2 g 2\mathrm{g} 2g、 3 g 3\mathrm{g} 3g、 5 g 5\mathrm{g} 5g、 10 g 10\mathrm{g} 10g、 20 g 20\mathrm{g} 20g 的砝码各若干枚(其总重 $ \le 1000$),可以表示成多少…

每日一题 --- 螺旋矩阵 II[力扣][Go]

螺旋矩阵 II 题目:59. 螺旋矩阵 II - 力扣(LeetCode) 给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。 示例 1: 输入:n 3 输出…

网络分析(蓝桥杯,acwing,并查集)

题目描述: 小明正在做一个网络实验。 他设置了 n 台电脑,称为节点,用于收发和存储数据。 初始时,所有节点都是独立的,不存在任何连接。 小明可以通过网线将两个节点连接起来,连接后两个节点就可以互相通…

202312 CSP认证 | 树上搜索

树上搜索 这题算是寒假期间自己先写了一遍,当时是20分超时了 当时的存储思路是,存储每一个节点的所有后代节点,然后在找到wsigma最小的节点之后用的集合操作。这导致了一个问题: 更新维护成本很高。每删除一个分支,都…

Electron 原生 UI 元素集成实践

Electron原生UI元素集成实践:菜单、托盘图标和对话框的运用 创建主菜单添加系统托盘图标使用对话框使用系统通知实现上下文菜单(右键菜单)结语 在 Electron 中,我们不仅可以利用 HTML5 和 JavaScript 构建应用程序的核心界面&…

python 爬虫爬取地理空间高程图GDEMV2 30m 中国地形

一.配置Python 爬虫 环境 from selenium import webdriver import time # from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.common.by import Byfrom selenium.webdriver.common.keys import Keys # from selenium.webdriver.comm…

Linux命令总结

1.目录切换 #切换到该目录下 usr 目录 cd usr #切换到上一层目录 cd ../ cd .. #切换到系统根目录 cd / #切换到用户主目录 cd ~ #切换到上一个操作所在目录 cd -2.目录操作 #显示目录中的文件和子目录的列表 ls /usr #目录下的所有目录和文件的详细信息 ll /usr #创建新目录…

【鸿蒙系统】 ---OpenHarmony加快本地编译(二)

💌 所属专栏:【鸿蒙系统】 😀 作  者:我是夜阑的狗🐶 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询! 💖 欢…