Xamarin开发:商场促销(策略设计模式)

Xamarin开发:商场促销(策略设计模式)

  • 一、介绍
  • 二、需求分析
  • 三、实现
  • 四、需求分析
    • 问题1解决方案
    • 问题2解决方案
  • 五、增加新需求
  • 六、代码优化与分析
  • 总结

一、介绍

本文引用《大话设计模式》第二章节的内容进行学习分析,仅供学习使用

这里接着我上一篇 Xamarin开发:基础 继续编写
这里采用策略设计模式进行编写,所谓的代码设计并不是单单指某一种的设计模式而已,比如我们接下来要介绍的策略设计模式实际上是基于简单工厂设计模式的改造而来的,所以在设计代码逻辑的时候不要忠于代码一定要使用某一种设计模式来实现,而应该是应该将需求细化,具体分析适合哪一种设计模式,我所认为的设计模式实际上就是将我们平时比较复杂的代码规范化、降低代码的重复性、冗余性的表现,让我们的代码更加的简单,让其他程序看到感觉之后感觉逻辑简单,代码清晰,这也是作为一名程序员应该具有的能力。

二、需求分析

先看一下需求,如下图
在这里插入图片描述

这里我们先抛开 计算方式 这一问题
仅仅实现简单的 输入单价输入数量,点击确认按钮计算出在 总计,并在TextView中显示,单价: xx 数量: xx 总计: xx
并且点击重置,有重置功能即可

这里对于刚开始接触编程的人来说可能分析并不会透彻,只为来实现功能而去实现,但是不要紧我们可以一步步的优化将我们的代码进行规范化,让别人看着思路清晰。

三、实现

这里就不在讲述我的点击时间和Label属性是如何注册和调用的了,如果不知道的可以看我上一篇文章

打开Vs 中的 ViewController.cs脚本

这是没有编写逻辑的脚本

namespace ShoppingMall{public partial class ViewController : NSViewController{public ViewController(IntPtr handle) : base(handle){}public override void ViewDidLoad(){base.ViewDidLoad();// Do any additional setup after loading the view.}public override NSObject RepresentedObject{get{return base.RepresentedObject;}set{base.RepresentedObject = value;// Update the view, if already loaded.}}}

这里将 确认点击 按钮的事件注册一下

 /// <summary>/// Makes the sure.确认按钮/// </summary>/// <param name="sender">Sender.</param>partial void MakeSure(NSButton sender){throw new NotImplementedException();}/// <summary>/// Resert the specified sender.重置按钮/// </summary>/// <param name="sender">Sender.</param>partial void Resert(NSButton sender){throw new NotImplementedException();}

编写逻辑如下

	/// <summary>/// The m price.单价/// </summary>private double m_price = 0d;/// <summary>/// The m amount.数量/// </summary>private double m_amount = 0d;/// <summary>/// The m totalmoney.未折扣价格/// </summary>private double m_totalmoney = 0d;/// <summary>/// Makes the sure.确认按钮/// </summary>/// <param name="sender">Sender.</param>partial void MakeSure(NSButton sender){if (string.IsNullOrEmpty(PriceField.StringValue) || string.IsNullOrEmpty(AmountField.StringValue))return;m_price = double.Parse(PriceField.StringValue);m_amount = double.Parse(AmountField.StringValue);m_totalmoney = m_price * m_amount;TotalPrice.StringValue = m_totalmoney.ToString();TextView.Value = "单价:" + m_price + " 数量:" + m_amount + " 正常收费 合计:" + m_totalmoney;}/// <summary>/// Resert the specified sender.重置按钮/// </summary>/// <param name="sender">Sender.</param>partial void Resert(NSButton sender){PriceField.StringValue = string.Empty;AmountField.StringValue = string.Empty;TextView.Value = string.Empty;TotalPrice.StringValue = "0.00";}

功能如下
在这里插入图片描述

四、需求分析

这里我们来分析一下上述代码:
问题1:代码中用到了很多double.Parse() 怎么解决?
问题2:这时候上面又提出新的需求,我们要采用一个打折处理,如何处理比较妥当?

问题1解决方案

这里编写一个工具类,直接string.ToDouble()即可

public static class Tools{public static double ToDouble(this string str) {double dbl = 0d;double.TryParse(str,out dbl);return dbl;}}

问题2解决方案

这里我们添加一个下拉菜单即可(Pop Up Button)
这里需要初始化一下下拉菜单的选项

这里在编写一个Const类,里面存放下拉列表选项:

public class Const{public static string[] PullDown = { "请选择计费方式", "正常收费", "八折" };}

注册下拉列表事件并写一个初始化的方法:

    /// <summary>/// Init this instance.初始化/// </summary>public void Init(){PullDown.RemoveAllItems();PullDown.AddItems(Const.PullDown);}/// <summary>/// Drops down.下拉列表选择/// </summary>/// <param name="sender">Sender.</param>partial void DropDown(NSPopUpButton sender){PullDown.Title = sender.TitleOfSelectedItem;}
这里的Init方法放在加载窗口之后直接执行public override void ViewDidLoad(){base.ViewDidLoad();Init();// Do any additional setup after loading the view.}

这里分析一下打折处理,我们可以把打折 正常收费作为一个对象处理,然后写一个抽象类让我们创建的对象去继承,最后写一个简单工厂去实例化对象,从而降低了代码的耦合性,使其后续的修改不会影响到其他类;

修改一下点击事件最后代码如下:

	/// <summary>/// Cash super.抽象类/// </summary>public abstract class CashSuper{public abstract double AcceptCash(double money);}/// <summary>/// Cash normal.正常/// </summary>public class CashNormal : CashSuper{public override double AcceptCash(double money){return money;}}/// <summary>/// Cash rebate.打折/// </summary>public class CashRebate : CashSuper{private double moneyRebate = 1d;public CashRebate(string moneyRebate) {this.moneyRebate = double.Parse(moneyRebate);}public override double AcceptCash(double money){return money * moneyRebate;}}

简单工厂:

	public class CashFactory{public static CashSuper CreateCashAccept(string type) {CashSuper super = null;switch (type){case "正常收费":super = new CashNormal();break;case "八折":super = new CashRebate("0.8");break;default:break;}return super;}}

点击事件修改

      /// <summary>/// The discount.折扣价/// </summary>private double m_discount = 0d;/// <summary>/// Makes the sure.确认按钮/// </summary>/// <param name="sender">Sender.</param>partial void MakeSure(NSButton sender){if (string.IsNullOrEmpty(PriceField.StringValue) || string.IsNullOrEmpty(AmountField.StringValue))return;m_price = PriceField.StringValue.ToDouble();m_amount = AmountField.StringValue.ToDouble();m_totalmoney = m_price * m_amount;//简单工厂模式CashSuper super = CashFactory.CreateCashAccept(PullDown.Title);m_discount = super.AcceptCash(m_totalmoney);TotalPrice.StringValue = m_discount.ToString();TextView.Value = "单价:" + m_price + " 数量:" + m_amount + " 合计:" + m_discount;}

在这里插入图片描述

五、增加新需求

这时候我们增加了一个满减的活动 满300减100

这时候我们分析,只需要在增加一个满减类即可,并且修改一下简单工厂就可以完美解决

新增类:

/// <summary>/// Cash return.返利/// </summary>public class CashReturn : CashSuper{private double moneyCondition = 0d;private double moneyReturn = 0d;public CashReturn(string moneyCondition,string moneyReturn) {this.moneyCondition = double.Parse(moneyCondition);this.moneyReturn = double.Parse(moneyReturn);}public override double AcceptCash(double money){if (money >= moneyCondition)return money - Math.Floor(money / moneyCondition) * moneyReturn;return money;}}

简单工厂类修改:

public class CashFactory{public static CashSuper CreateCashAccept(string type) {CashSuper super = null;switch (type){case "正常收费":super = new CashNormal();break;case "八折":super = new CashRebate("0.8");break;case "满300减100":super = new CashReturn("300","100");break;default:break;}return super;}}

功能如下:
在这里插入图片描述

六、代码优化与分析

这里我们看一下 确认按钮 的点击事件中的逻辑
现在我们获取结果的时候我们需要调用两个类一个是抽象类,另一个是工厂类,这样不利于代码的清晰度,这时候我们需要将简单工厂与策略模式结合一下,让我们的代码更加简洁。

如下:

public class CashContext{private CashSuper m_cashsuper = null;public CashContext(string type){switch (type){case "正常收费":m_cashsuper = new CashNormal();break;case "八折":m_cashsuper = new CashRebate("0.8");break;case "满300减100":m_cashsuper = new CashReturn("300", "100");break;default:m_cashsuper = null;break;}}public double GetResult(double money){return m_cashsuper.AcceptCash(money);}}

点击事件修改:

/// <summary>/// Makes the sure.确认按钮/// </summary>/// <param name="sender">Sender.</param>partial void MakeSure(NSButton sender){if (string.IsNullOrEmpty(PriceField.StringValue) || string.IsNullOrEmpty(AmountField.StringValue))return;m_price = PriceField.StringValue.ToDouble();m_amount = AmountField.StringValue.ToDouble();m_totalmoney = m_price * m_amount;简单工厂模式//CashSuper super = CashFactory.CreateCashAccept(PullDown.Title);//m_discount = super.AcceptCash(m_totalmoney);//简单工厂与策略模式结合CashContext cc = new CashContext(PullDown.Title);m_discount = cc.GetResult(m_totalmoney);TotalPrice.StringValue = m_discount.ToString();TextView.Value = "单价:" + m_price + " 数量:" + m_amount + " 合计:" + m_discount;}

这样使得我们的代码更加的简洁,对一个类进行操作即可

UML类图:在这里插入图片描述

总结

实际上策略模式实际上是一种定义一系列算法的方法,概念来讲所有的算法都是实现相同的工作,只是实现不一样,它可以以相同的方式调用所有算法,减少了各种算法类与算法类之间的耦合度。

好处:简化了单元测试,每个算法都有自己的类,可以通过自身的接口进行单独测试,不影响其他类。

注意:策略模式是封装各种算法,所以避免不了很多的判断,那么这个时候不管是ifswitch其实都不是最好的选择,我们那可以选择使用反射来进行,反射在之后的博客中讲解。

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

【Redis前奏曲】初识Redis

文章目录 一.Redis的一些特性(优点)1. 在内存中存储数据2. 可编程的3. 可扩展的4.持久化5. 聚集(集群)6. 高可用Redis快的原因 二. 使用案例1.数据库2. 缓存3. 消息队列 一.Redis的一些特性(优点) 我们在上一篇博客中说到,Redis是一个在内存中存储数据的中间件.用作数据库,数据…

深度解析TB用户购物行为:系统搭建与优化

深度解析TB用户购物行为&#xff1a;系统搭建与优化 引言系统搭建数据集技术选型 系统功能1. 用户维度分析2. 产品维度分析3. 聚类结果分析 创新点系统优化与展望优化展望 结语 引言 在电商时代&#xff0c;了解用户购物行为并从中提取有价值的信息对于企业制定营销策略和优化…

MySQL 8.0 InnoDB Tablespaces之General Tablespaces(通用表空间/一般表空间)

文章目录 MySQL 8.0 InnoDB Tablespaces之General Tablespaces&#xff08;通用表空间/一般表空间&#xff09;General tablespaces&#xff08;通用表空间/一般表空间&#xff09;通用表空间的功能通用表空间的限制 创建通用表空间&#xff08;一般表空间&#xff09;创建语法…

键盘字符(#键)显示错误

当屏幕上显示的键与键盘上按下的键不同时&#xff0c;尤其是 # 键。大多数情况下&#xff0c;此错误是由于 raspbian 和 NOOBS 软件的默认英国键盘配置所致。 解决方案&#xff1a; 要解决此问题&#xff0c;您需要将配置更改为您自己的键盘或语言的配置。这可以通过转到树莓派…

Java 读取超大excel文件

注意&#xff1a;此参考解决方案只是针对xlsx格式的excel文件&#xff01; Maven <dependency><groupId>com.monitorjbl</groupId><artifactId>xlsx-streamer</artifactId><version>2.2.0</version> </dependency>读取方式1…

PostgreSQL 数据库归档最近被问及的问题问题 与 4 毋 处世学

开头还是介绍一下群&#xff0c;如果感兴趣PolarDB ,MongoDB ,MySQL ,PostgreSQL ,Redis, Oceanbase, Sql Server等有问题&#xff0c;有需求都可以加群群内&#xff0c;可以解决你的问题。加群请联系 liuaustin3 &#xff0c;&#xff08;共1790人左右 1 2 3 4 5&#xff0…

LMX2571 芯片配置Verliog SPI驱动

前言 本实验使用ZYNQ的PL(FPGA)对LMX2571芯片进行配置&#xff0c;以下连接为相关的原理和软件使用资料。 TICS Pro 配置时钟芯片 文献阅读–Σ-Δ 小数频率合成器原理 LMX2571芯片数据手册 一、LMX2571配置时序分析 1.1 写时序 LMX2571使用24位寄存器进行编程。一个24位移位…

CSS去掉按钮阴影 | css去掉按钮边框 | 注意改变搜索的关键词、搜索方式

上图是在谷歌浏览器中运行的结果 button {box-shadow: none;height: 50px;width: 100px;background-color: white;border-color: white; }写了以上的css&#xff0c;发现按钮还是有阴影一样的东西&#xff0c;查阅网络资料的时候也一直在搜索“如何去掉按钮阴影”&#xff0c;…

计算数组中某一数字出现次数

计算数组中某一数字出现次数 思路实现普通数组的方法双向列表的方法 总结 思路 这个比较简单&#xff0c;思路其实就是遍历数组中所有的数字做一下对比&#xff0c;有的话记录一下即可。但是这几天看到了个双向列表LinkList的方法&#xff0c;所以拿出来做一下对比看看。 实现…

网站提示“不安全”怎么解决

在互联网中&#xff0c;安全问题至关重要。访问某些网站时&#xff0c;可能会遇到“不安全”警告&#xff0c;通常是由于缺乏SSL证书。SSL证书是数字证书&#xff0c;用于确保互联网通信的安全和保密。 “不安全”问题通常源于缺少SSL证书。SSL通过加密通信&#xff0c;防止第三…

“2023年的技术发展与个人成长:回顾与展望“

文章目录 每日一句正能量前言工作生活未来展望后记 每日一句正能量 凡事顺其自然&#xff0c;遇事处于泰然&#xff0c;得意之时淡然&#xff0c;失意之时坦然&#xff0c;艰辛曲折必然&#xff0c;历尽沧桑悟然。 前言 在这快速发展的信息时代&#xff0c;技术的进步和创新不…

CSS 向上扩展动画

上干货 <template><!-- mouseenter"startAnimation" 表示在鼠标进入元素时触发 startAnimation 方法。mouseleave"stopAnimation" 表示在鼠标离开元素时触发 stopAnimation 方法。 --><!-- 容器元素 --><div class"container&q…

MyBatis标签及其应用示例

MyBatis标签及其应用示例 1. select 1.1 标签属性 id唯一的标识符parameterType传给此语句的参数的全路径名或别名如&#xff1a;com.xxx.xxx.demo.entity.User或userresultType语句返回值类型或别名。如果是集合List&#xff0c;此处填写集合的泛型T&#xff0c;而不是集合…

SCT82630DHKR——5.5V-65V Vin同步降压控制器,可替代LM5145

描述&#xff1a; SCT82630是一款65V电压模式控制同步降压控制器&#xff0c;具有线路前馈。40ns受控高压侧MOSFET的最小导通时间支持高转换比&#xff0c;实现从48V输入到低压轨的直接降压转换&#xff0c;降低了系统复杂性和解决方案成本。如果需要&#xff0c;在低至6V的输…

【MySQL】数据库并发控制:悲观锁与乐观锁的深入解析

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a; 数 据 库 ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 悲观锁&#xff08;Pessimistic Locking&#xff09;: 乐观锁&#xff08;Optimistic Locking&#xff09;: 总结&#x…

SpringBoot3 应用分析

SpringBoot3-快速入门 1、简介 1. 前置知识 Java17Spring、SpringMVC、MyBatisMaven、IDEA 2. 环境要求 环境&工具版本&#xff08;or later&#xff09;SpringBoot3.0.5IDEA2021.2.1Java17Maven3.5Tomcat10.0Servlet5.0GraalVM Community22.3Native Build Tools0.9.1…

<JavaEE> TCP 的通信机制(五) -- 延时应答、捎带应答、面向字节流

目录 TCP的通信机制的核心特性 七、延时应答 1&#xff09;什么是延时应答&#xff1f; 2&#xff09;延时应答的作用 八、捎带应答 1&#xff09;什么是捎带应答&#xff1f; 2&#xff09;捎带应答的作用 九、面向字节流 1&#xff09;沾包问题 2&#xff09;“沾包…

深度学习之RNN

1.循环神经网络 在时间t的时候&#xff0c;对于单个神经元来讲它的输出y(t)如下 wx是对于输入x的权重&#xff0c;wy是对于上一时刻输出的权重 所以循环神经网络有两个权重。 如果有很多这样的神经元并排在一起 则在t时刻的输出y为 这时输入输出都是向量 2.记忆单元 由于循…

liunx系统突然不能启动jar

启动命令 nohup java -jar /date/gd_ly/jar/mssda-platform-backend-0.0.1-SNAPSHOT.jar -Dspring.config.location/date/gd_ly/jar/application-dev.yml 报错信息 Error: A JNI error has occurred, please check your installation and try again Exception in thread &q…

【起草】【第五章】定制ChatGPT数字亲人

身为普普通通的我们&#xff0c;不知道亲人们在哪一天就要离开这个世界 &#xff1f; 作为普普通通的程序员&#xff0c;我们可以为我们的亲人做点什么 &#xff1f; 让他们以某种形式留在人世间 ? 对话&#xff5c;6岁女孩病逝捐器官&#xff0c;妈妈&#xff1a;她去当天使…