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://www.mfbz.cn/a/276744.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java设计模式-装饰者模式

目录 一、星巴克咖啡订单项目 二、装饰者模式 &#xff08;一&#xff09;定义 &#xff08;二&#xff09;原理 &#xff08;三&#xff09;装饰者模式解决星巴克咖啡订单 一、星巴克咖啡订单项目 星巴克咖啡订单项目&#xff08;咖啡馆&#xff09;&#xff1a; 1) 咖…

菜鸟学习vue3笔记-vue hooks初体验

import { ref } from "vue"; export default function () {let a1 ref(1);let a2 ref(5);let c ref(0);function add() {a1.value;a2.value;}return {add,a1,a2,c,}; }<template><div><p>第一个数字{{ a1 }}</p><p>第二个数字{{ a2…

java勤工助学信息管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java Web勤工助学信息管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境 为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为M…

Java线上问题排查思路

1、Java 服务常见问题 Java 服务的线上问题从系统表象来看大致可分成两大类: 系统环境异常、业务服务异常。 系统环境异常&#xff1a;主要从CPU、内存、磁盘、网络四个方面考虑。比如&#xff1a;CPU 占用率过高、CPU 上下文切换频率次数较高、系统可用内存长期处于较低值、…

K8s实战-基于LivenessProbe健康检查

LivenessProbe探针用于判断容器是否存活&#xff0c;如果探测到容器不健康&#xff0c;则kubelet将杀掉该容器&#xff0c;然后根据重启策略处理。 LivenessProbe的实现方式&#xff1a; ExecAction&#xff1a;在容器内部执行一个命令&#xff0c;如果该命令的返回码为0&…

计算机毕业设计 基于SpringBoot的高校危化试剂仓储管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

最短路径(数据结构实训)(难度系数100)

最短路径 描述&#xff1a; 已知一个城市的交通路线&#xff0c;经常要求从某一点出发到各地方的最短路径。例如有如下交通图&#xff1a; 则从A出发到各点的最短路径分别为&#xff1a; B&#xff1a;0 C&#xff1a;10 D&#xff1a;50 E&#xff1a;30 F&#xff1a;60 输…

白话机器学习的数学-1-回归

1、设置问题 投入的广告费越多&#xff0c;广告的点击量就越高&#xff0c;进而带来访问数的增加。 2、定义模型 定义一个函数&#xff1a;一次函数 y ax b &#xff08;a 是斜率、b 是截距&#xff09; 定义函数&#xff1a; 3、最小二乘法 例子&#xff1a; 用随便确定的参…

BDTC2023:CloudberryDB开源创新与实践

中国大数据技术大会&#xff08;BDTC&#xff09;由中国计算机学会&#xff08;CCF&#xff09;创立于2008年&#xff0c;已经成为国内外极具行业实践的专业大数据交流平台。12月22日-24日&#xff0c;第十七届中国大数据技术大会&#xff08;BDTC 2023&#xff09;在广州举行。…

文字识别技术在未来会有怎样的发展?

随着科技的不断发展&#xff0c;文字识别技术也在不断地改进和完善。未来&#xff0c;文字识别技术将会在更多的领域得到应用&#xff0c;并且将会更加智能化、高效化和个性化。 首先&#xff0c;随着深度学习技术的不断发展&#xff0c;文字识别技术将会更加智能化。目前&…

ubuntu22下安装minconda

bing 搜索 canda install 找到官方网站 https://docs.conda.io/projects/miniconda/en/latest/ 这里我们安装minconda。 官网有安装方法。 mkdir -p ~/miniconda3 wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/miniconda3/miniconda.sh…

docker的基本管理和相关概念

docker的基本管理和概念 docker&#xff1a;开源的应用容器引擎。基于go语言开发的。运行在linux系统当中的开源的&#xff0c;轻量级的“虚拟机” docker的容器技术可以在一台主机上轻松的为任何应用创建一个轻量级的&#xff0c;可移植的&#xff0c;自给自足的容器 docke…

Java 读取超大excel文件

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

Android画布Canvas矩阵Matrix放大裁剪Rect区域的Bitmap,Kotlin

Android画布Canvas矩阵Matrix放大裁剪Rect区域的Bitmap&#xff0c;Kotlin private fun mydraw() {val originBmp BitmapFactory.decodeResource(resources, R.mipmap.pic).copy(Bitmap.Config.ARGB_8888, true)val newBmp Bitmap.createBitmap(originBmp.width, originBmp.h…

爬虫基础一(持续更新)

爬虫概念&#xff1a; 通过编写程序&#xff0c;模拟浏览器上网&#xff0c;然后让其去互联网上抓取数据的过程 分类&#xff1a; 1&#xff0c;通用爬虫&#xff1a;抓取一整张页面数据 2&#xff0c;聚焦爬虫&#xff1a;抓取页面中的局部内容 3&#xff0c;增量式爬虫&…

CUMT--Java--线程

目录 一、线程 1、概述 2、Java线程模型 3、主线程 二、创建线程 1、继承Thread类 2、实现Runnable接口 3、使用Callable和Future接口 三、线程生命周期 1、新建和就绪状态 2、运行和阻塞状态 3、死亡状态 四、线程优先级 五、线程同步 1、非同步情况 2、同步…

浅谈WPF之控件模板Control Template和数据模板Data Template

WPF不仅支持传统的Windows Forms编程的用户界面和用户体验设计&#xff0c;同时还推出了以模板为核心的新一代设计理念。在WPF中&#xff0c;通过引入模板&#xff0c;将数据和算法的“内容”和“形式”进行解耦。模板主要分为两大类&#xff1a;数据模板【Data Template】和控…

创建加密分区或者文件

文章目录 [GParted 中已清除的分区与未格式化的分区](https://superuser.com/questions/706624/cleared-vs-unformatted-partition-in-gparted)创建加密分区解密创建的加密分区以便挂载格式化设备未具体的格式&#xff08;这里为ext4格式&#xff09;创建挂载点目录挂载加密的文…

java在线票务系统(选座)Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java servlet 在线票务系统&#xff08;选座&#xff09;管理系统是一套完善的java web信息管理系统 系统采用serlvetdaobean&#xff08;mvc模式)&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要…

深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第六节 理解垃圾回收GC,提搞程序性能

深入浅出图解C#堆与栈 C# Heaping VS Stacking 第六节 理解垃圾回收GC&#xff0c;提搞程序性能 [深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第一节 理解堆与栈](https://mp.csdn.net/mdeditor/101021023)[深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第二节 栈基…