设计模式--策略模式(由简单工厂到策略模式到两者结合图文详解+总结提升)

目录

  • 概述
    • 概念
    • 组成
    • 应用场景
    • 注意事项
    • 类图
  • 衍化过程
    • 需求
    • 简单工厂实现
      • 代码
    • 策略模式
      • 代码
    • 策略模式+简单工厂
      • 代码
  • 总结升华
    • 版本迭代的优化点及意义
    • 什么样的思路进行衍化的
    • 扩展思考--如何理解策略与算法

概述

概念

    策略模式是一种行为型设计模式,它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。

组成

1、Context(上下文):用于维护策略类的引用,并在运行时根据需要选择合适的策略。
2、Strategy(策略):定义一个公共接口,用于封装不同的算法或行为。
3、ConcreteStrategy(具体策略):实现策略接口,提供具体的算法或行为。

应用场景

    当一个系统需要根据不同的情况选择不同的算法或行为时,可以使用策略模式。
    当一个类中有多个条件语句,每个条件语句对应一个算法或行为时,可以考虑使用策略模式简化代码。

注意事项

    策略模式将算法或行为封装在不同的策略类中,因此需要对策略类进行合理的设计和组织。
    策略模式需要在运行时动态选择策略,因此需要在客户端代码中设置策略的选择逻辑。

类图

在这里插入图片描述

衍化过程

需求

    商场根据不同的促销活动,以不同的方式对商品进行折扣计算和结算。具体来说,商场收银的需求可以分为以下几个阶段的变化过程:

  1. 初始需求:商场最开始只有一种收费方式,即正常收费,即不打折不返现,直接按照原价进行结算。

  2. 变化需求1:商场决定进行促销活动,对部分商品进行打折处理。这时,商场需要根据商品的折扣率来计算折扣后的价格,并进行结算。

  3. 变化需求2:商场进一步决定进行满减活动,即满足一定条件后,可以返现一定金额。这时,商场需要根据商品的价格和满减条件来计算返现后的价格,并进行结算。

  4. 变化需求3:商场希望能够根据不同的促销活动,动态地选择不同的收费方式。这时,商场引入了策略模式,将不同的收费方式封装在不同的策略类中,并在运行时根据需要选择合适的策略进行结算。

前两版比较简单,这里不再赘述,主要从需求3说起:
    分为简单工厂实现、策略模式实现、简单工厂+策略模式

简单工厂实现

代码

收费相关类

//收费抽象类
abstract class CashSuper {public abstract double acceptCash(double money);
}
//正常收费类
public class CashNormal extends CashSuper {@Overridepublic double acceptCash(double money) {return money;}
}
//打折收费类
public class CashRebate extends CashSuper {private double moneyRebate=1;public CashRebate(String moneyRebate){this.moneyRebate= Double.parseDouble(moneyRebate);}@Overridepublic double acceptCash(double money) {return money*moneyRebate;}
}
//满减收费类
public class CashReturn extends CashSuper {private double moneyCondtion;private double moneyReturn;public CashReturn(String moneyCondition,String moneyReturn){this.moneyCondtion= Double.parseDouble(moneyCondition);this.moneyReturn= Double.parseDouble(moneyReturn);}@Overridepublic double acceptCash(double money) {double result=money;if (money>=moneyCondtion){result=money-Math.floor(money/moneyCondtion)*moneyReturn;}return result;}
}

工厂

public class CashFactory {public  CashSuper creatCashAccept(String type) {CashSuper cs = null;switch (type){case "正常收费":cs=new CashNormal();break;case "满300返100":cs=new CashReturn("300","100");break;case "打八折":cs=new CashRebate("0.8");break;}return cs;}

客户端

public class Client {public static void main(String[] args) {CashFactory factory=new CashFactory();CashSuper cs=factory.creatCashAccept("满300返100");double result=cs.acceptCash(300);System.out.println(result);}
}

策略模式

类图
在这里插入图片描述

NS图
在这里插入图片描述

代码

收费上下文类

public class CashContext {private CashSuper cs;public CashContext(CashSuper csuper){this.cs=csuper;}public double getResult(double money){return cs.acceptCash(money);}}

客户端

public class Client {public static void main(String[] args) {//传的是不同的策略对象CashContext selectNormal = new CashContext(new CashNormal());CashContext selectRebate = new CashContext(new CashRebate("0.8"));CashContext selectReturn = new CashContext(new CashReturn("300","100"));System.out.println("选择正常:"+selectNormal.getResult(300));System.out.println("选择打八折:"+selectRebate.getResult(300));System.out.println("选择满减:"+selectReturn.getResult(300));}
}

策略模式+简单工厂

在这里插入图片描述

代码

收费上下文类(其中包括简单工厂)

public class CashContext {private CashSuper cs=null;//参数是个字符串,而不是收费策略对象public CashContext(String type){switch (type){case "正常收费":cs=new CashNormal();break;case "满300返100":cs=new CashReturn("300","100");break;case "打8折":cs=new CashRebate("0.8");break;}}public double getResult(double money){return cs.acceptCash(money);}}

客户端

public class Client {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);System.out.println("请输入销售模式:");String type = scanner.nextLine();//传的是字符串,而不是具体的策略类CashContext cash = new CashContext(type);System.out.println("请输入原价");double price = Double.parseDouble(scanner.nextLine());System.out.println("最后收费" + cash.getResult(price));}
}

总结升华

版本迭代的优化点及意义

1.前两版到简单工厂
     将算法封装,每一个优惠策略都是一个单独的类,而且它们都继承自一个抽象类,抽象类是此版本的一个巨大进步,出现了面向对象以及类的概念,后续的扩充、维护、复用打下了基础。

2.简单工厂到策略模式
    使用简单工厂违反开闭原则,考虑到了算法变化性,要这些算法随时可以互相替换,也正是策略模式概念中提到的,而封装变化点是面向对象一种重要的思维方式。

3.策略模式到简单工厂+策略模式
    策略模式中实例化对象还是交给了客户端去完成,结合了简单工厂之后,实例化对象由CashContext来完成,可以在客户端消除条件语句。

    另外,简单工厂模式客户端需要认识CashSuper和CashFactory,而简单工厂+策略模式,客户端之需要认识CashContext一个类就可以,降低了耦合性。
在这里插入图片描述

什么样的思路进行衍化的

有限到无限:
    依据业务需求,如果存在潜在的需要,就用无限的思维去进行设计(看到switch case就要思考是否需要无限的思维)
    如何去做到无限,使用想象力与创造力把有限的需求变成无限的需求,同时使用有限的方法去实现,落实到代码上是依据软件工程的7大原则和23个设计模式(独立或组合),达到可扩充、可复用、可维护的目标。

扩展思考–如何理解策略与算法

    策略模式中提到策略模式定义了算法家族,看类图的时候貌似策略和算法是一个概念,但是两者真的是一样的吗,如无必要勿增实体。那它们是什么关系呢,有没有一种可能,策略和算法并不是一一对应的关系,而独立算法和算法的组合都可以称之为策略呢,就像类图中Strategy与Context是聚合关系。这只是一个想法,策略模式也没有结束,后续还有策略模式+工厂方法+反射的实现,以及我所猜测的算法的组合也可称之为策略,敬请期待。

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

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

相关文章

flask中的flask-login

flask中的flask-login 在 Flask 中,用户认证通常是通过使用扩展库(例如 Flask-Login、Flask-HTTPAuth 或 Flask-Security)来实现的。 本文详细地解释下 Flask 中的用户认证。这里是用 Flask-Login 插件为例,这是一个处理用户会话…

21.Netty源码之编码器

highlight: arduino-light Netty如何实现自定义通信协议 在学习完如何设计协议之后,我们又该如何在 Netty 中实现自定义的通信协议呢?其实 Netty 作为一个非常优秀的网络通信框架,已经为我们提供了非常丰富的编解码抽象基类,帮助我…

C# 根据图片的EXIF自动调整图片方向

PropertyItems 代码 /// <summary>/// 根据图片exif调整方向/// </summary>/// <param name"img"></param>public void RotateImage(Bitmap img){var exif img.PropertyItems;byte orien 0;var item exif.Where(m > m.Id 274).ToArra…

16、外部配置源与外部配置文件及JSON配置

外部配置源与外部配置文件及JSON配置 application.properties application.yml 这些是配置文件&#xff0c; 命令行配置、环境变量配置、系统属性配置源&#xff0c;这些属于配置源。 外部配置源的作用&#xff1a; Spring Boot相当于对Spring框架进行了封装&#xff0c;Spri…

策略模式(C++)

定义 定义一系列算法&#xff0c;把它们一个个封装起来&#xff0c;并且使它们可互相替换((变化)。该模式使得算法可独立手使用它的客户程序稳定)而变化(扩展&#xff0c;子类化)。 ——《设计模式》GoF 使用场景 在软件构建过程中&#xff0c;某些对象使用的算法可能多种多…

viewerjs 如何新增下载图片功能(npm包补丁)

文章目录 先实现正常的效果实现下载图片改变viewerjs的build函数源码改变之后&#xff0c;执行npm i 之后node_modules源码又变回了原样 1、viwerjs所有功能都很完善&#xff0c;但唯独缺少了图片的下载 2、需求&#xff1a;在用viwerjs旋转图片后&#xff0c;可以直接下载旋转…

规划模型Matlab代码

文章目录 数学规划定义一般形式分类 1.线性规划(linear programming)2.非线性规划(nonlinear programming)3. 整数规划(integer programming)4. 0-1规划(0-1 programming)5. 最大最小化模型6. 多目标规划模型7.敏感性分析&#xff08;对权重&#xff09;[例题] 数学规划定义 数…

Stable Diffusion - SDXL 1.0 全部样式设计与艺术家风格的配置与提示词

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/132072482 来源于 Anna Dittmann 安娜迪特曼&#xff0c;艺术家风格的图像&#xff0c;融合幻想、数字艺术、纹理等样式。 SDXL 是 Stable Diffus…

Git常见问题

git clone 提示OpenSSL SSL_read git clone 时提示Connection was reset, errno 10054类错误 fatal: unable to acce ss https://github.com/fex-team/ueditor.git/: OpenSSL SSL_read: Connection was reset, errno 10054 备注&#xff1a;以下方法只是归纳整理&#xff0c;…

【零基础学Rust | 基础系列 | 基础语法】变量,数据类型,运算符,控制流

文章目录 简介&#xff1a;一&#xff0c;变量1&#xff0c;变量的定义2&#xff0c;变量的可变性3&#xff0c;变量的隐藏 二、数据类型1&#xff0c;标量类型2&#xff0c;复合类型 三&#xff0c;运算符1&#xff0c;算术运算符2&#xff0c;比较运算符3&#xff0c;逻辑运算…

Apache Flink概述

Flink 是构建在数据流之上的一款有状态的流计算框架&#xff0c;通常被人们称为第三代大数据分析方案 第一代大数据处理方案&#xff1a;基于Hadoop的MapReduce 静态批处理 | Storm 实时流计算 &#xff0c;两套独立的计算引擎&#xff0c;难度大&#xff08;2014年9月&#x…

Hyperledger Fabric 使用 CouchDB 和复杂智能合约开发

前言 在上个实验中&#xff0c;我们已经实现了简单智能合约实现及客户端开发&#xff0c;但该实验中智能合约只有基础的增删改查功能&#xff0c;且其中的数据管理功能与传统 MySQL 比相差甚远。本文将在前面实验的基础上&#xff0c;将 Hyperledger Fabric 的默认数据库支持 …

Kafka3.0.0版本——Broker(Zookeeper服务端存储的Kafka相关信息)

目录 一、启动zookeeper集群及kafka集群服务启动1.1、先启动三台zookeeper集群服务&#xff0c;再启动三台kafka集群服务1.2、使用PrettyZoo连接zookeeper客户端工具 二、在zookeeper服务端存储的Kafka相关信息 一、启动zookeeper集群及kafka集群服务启动 1.1、先启动三台zook…

C++初阶引用

目录 引用引用的特性使用输出型参数作返回值小总结引用的权限引用和指针 引用 引用不是新定义一个变量&#xff0c;而是给已存在变量取了一个别名&#xff0c;编译器不会为引用变量开辟内存空间&#xff0c;它和它引用的变量共用同一块内存空间。 比如周树人&#xff0c;在外…

探索创意之路:稳定扩散AI绘画指南

文章目录 引言第一部分&#xff1a;了解稳定扩散AI绘画1.1 稳定扩散AI绘画简介1.2 稳定扩散AI绘画的优势 第二部分&#xff1a;使用稳定扩散AI绘画2.1 获取稳定扩散AI绘画工具2.2 准备绘画素材和设置参数2.3 进行AI绘画 第三部分&#xff1a;发挥创意&#xff0c;创作精彩绘画3…

阿里云AK创建

要在阿里云上创建 Access Key&#xff08;AK&#xff09;&#xff0c;您需要按照以下步骤进行操作&#xff1a; 登录到阿里云控制台&#xff08;[https://www.aliyun.com/?utm_contentse_1014243503)&#xff09;。 点击右上方的主账号&#xff0c;点击“AccessKey管理”。 …

P1064 [NOIP2006 提高组] 金明的预算方案 (依赖背包问题)(内附封面)

[NOIP2006 提高组] 金明的预算方案 题目描述 金明今天很开心&#xff0c;家里购置的新房就要领钥匙了&#xff0c;新房里有一间金明自己专用的很宽敞的房间。更让他高兴的是&#xff0c;妈妈昨天对他说&#xff1a;“你的房间需要购买哪些物品&#xff0c;怎么布置&#xff0…

R语言【Tidyverse、Tidymodel】的机器学习方法

机器学习已经成为继理论、实验和数值计算之后的科研“第四范式”&#xff0c;是发现新规律&#xff0c;总结和分析实验结果的利器。机器学习涉及的理论和方法繁多&#xff0c;编程相当复杂&#xff0c;一直是阻碍机器学习大范围应用的主要困难之一&#xff0c;由此诞生了Python…

python人工智能可以干什么,python人工智能能干什么

大家好&#xff0c;给大家分享一下python做人工智能需要什么水平&#xff0c;很多人还不知道这一点。下面详细解释一下。现在让我们来看看&#xff01; 人工智能包含常用机器学习和深度学习两个很重要的模块&#xff0c;而python拥有matplotlib、Numpy、sklearn、keras等大量的…

【深度学习笔记】深度学习框架

本专栏是网易云课堂人工智能课程《神经网络与深度学习》的学习笔记&#xff0c;视频由网易云课堂与 deeplearning.ai 联合出品&#xff0c;主讲人是吴恩达 Andrew Ng 教授。感兴趣的网友可以观看网易云课堂的视频进行深入学习&#xff0c;视频的链接如下&#xff1a; 神经网络和…