这次我们依旧是从一个简单的小问题开始~鉴于本人不会C#的可视化编程QAQ,,所以以后涉及UI的一律用unity处理,不过UI不是主要部分,我做的也比较简陋,不要在意哈,大家用什么都好~~~那么我们先考虑最简单的方法,只需要一个单价和数量的输入文本框,一个记录总费用的字段,然后计算每个商品的费用显示出来就好了就好了,就像下面这样
那么这次的问题就是:做一个商场收银软件,营业员要根据客户所购买的商品单价和数量,向客户收费。
文章图片
public class 策略例子 : MonoBehaviour
{
public InputField prices;
public InputField nums;
public Text showTex;
public Button okBtn;
private float total = 0.0f;
// Start is called before the first frame update
void Start()
{
okBtn.onClick.AddListener(OnClickOkBtn);
}public void OnClickOkBtn()
{
var price = int.Parse(prices.text);
var num = int.Parse(nums.text);
total += (price * num);
showTex.text = total.ToString();
}
}
这样是可以了,但是如果商场要搞活动打折呢?
那我们加个打折下拉框吧
文章图片
public class 策略例子 : MonoBehaviour
{
public InputField prices;
public InputField nums;
public Text showTex;
public Button okBtn;
public Dropdown dropdown;
private float total = 0.0f;
private float discount = 1.0f;
// Start is called before the first frame update
void Start()
{
okBtn.onClick.AddListener(OnClickOkBtn);
} public void OnClickOkBtn()
{
var price = int.Parse(prices.text);
var num = int.Parse(nums.text);
OnDropDownChange(dropdown.options[dropdown.value].text);
total += (price * num)* discount;
showTex.text = "当前价格:"+total.ToString();
}
public void OnDropDownChange(string arg)
{
switch (arg)
{
case "八折":
discount = 0.8f;
break;
case "五折":
discount = 0.5f;
break;
case "三折":
discount = 0.3f;
break;
default:
break;
}
}
}
但是商场老板就喜欢玩新花样,现在又想加个满300反100的促销活动,现在是不是感觉就有点复杂了呢
但是想想这么多东西打折基本都是一样的,只不过打折方式不一样,我们能不能用简单工厂处理呢?(打一折和打九折只是形式不同,抽象分析出来,同时所有的打折算法都是一样的,所以应该每一种打折算法是一个类。)
面向对象编程,并不是类越多越好,类的划分是为了封装,但分类的基础是抽象,具有相同属性和功能的对象的抽象集合才是类。
public class 策略例子 : MonoBehaviour
{
public InputField prices;
public InputField nums;
public Text showTex;
public Button okBtn;
public Dropdown dropdown;
private float total = 0.0f;
private float discount = 1.0f;
// Start is called before the first frame update
void Start()
{
okBtn.onClick.AddListener(OnClickOkBtn);
} public void OnClickOkBtn()
{
var price = int.Parse(prices.text);
var num = int.Parse(nums.text);
var csuper = CashFactory.createCashAccept(dropdown.options[dropdown.value].text);
total = num * price;
total = csuper.acceptCash(total);
showTex.text = "当前价格:"+total.ToString();
}
}
//收费父类
abstract class CashSuper
{
//现金收取父类,收取现金,参数为原价,返回打折后的价
public abstract float acceptCash(float money);
}
class CashNromal: CashSuper
{
public override float acceptCash(float money)
{
return money;
}
}
class CashRebate : CashSuper
{
private float moneyRebate = 1f;
public CashRebate(float moneyRebate)
{
this.moneyRebate = moneyRebate;
}
public override float acceptCash(float money)
{
return moneyRebate * money;
}
}
class CashReturn: CashSuper
{
private float moneyCondition = 0.0f;
private float moneyReturn = 0.0f;
public CashReturn(float moneyCondition,float moneyReturn)
{
this.moneyCondition = moneyCondition;
this.moneyReturn = moneyReturn;
} public override float acceptCash(float money)
{
float result = money;
if (money >= moneyCondition)
{
result = money - Mathf.Floor((float)money / moneyCondition) * moneyReturn;
}
return result;
}
//收费工厂类
public class CashFactory
{
public static CashSuper createCashAccept(string type)
{
CashSuper cs = null;
switch (type)
{
case "正常收费":
cs = new CashNromal();
break;
case "满300反100":
cs = new CashReturn(300,100);
break;
case "打八折":
cs = new CashRebate(0.8f);
break;
default:
break;
}
return cs;
}
}
}
这样代码看上去是不是好多了呢,如果在加别的活动的话只需要增加相应的子类和UI下拉框内容即可。但是工厂本身包括了所有的收费方式,商场可能会经常性的更改打折模式,每次维护或扩展收费方式都需要去改动这个工厂,这并不是一个最好的办法。面对算法的时长变动,我们应该用一个更好地设计模式处理。
策略模式
策略模式定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。
让我们先看一下策略算法的基本结构
文章图片
public class 策略模式 : MonoBehaviour
{
Context context;
private void Start()
{
context = new Context(new ConcreteStrategyA());
context.ContextInterface();
context = new Context(new ConcreteStrategyB());
context.ContextInterface();
}
}
abstract class Strategy
{
//算法方法
public abstract void AlgorithmInterfacs();
}
//具体算法
class ConcreteStrategyA: Strategy
{
public override void AlgorithmInterfacs()
{
Debug.Log("算法A实现");
}
}
class ConcreteStrategyB : Strategy
{
public override void AlgorithmInterfacs()
{
Debug.Log("算法B实现");
}
}
class Context
{
Strategy strategy;
public Context(Strategy strategy)
{
this.strategy = strategy;
}
//上下接口
public void ContextInterface()
{
strategy.AlgorithmInterfacs();
}
}
那我们把刚才的例子改一下吧(这个其实是策略模式与简单工厂结合使用)
public class 策略例子 : MonoBehaviour
{
public InputField prices;
public InputField nums;
public Text showTex;
public Button okBtn;
public Dropdown dropdown;
private float total = 0.0f;
private float discount = 1.0f;
// Start is called before the first frame update
void Start()
{
okBtn.onClick.AddListener(OnClickOkBtn);
} public void OnClickOkBtn()
{
var price = int.Parse(prices.text);
var num = int.Parse(nums.text);
CashContext cc = new CashContext(dropdown.options[dropdown.value].text);
total = num * price;
total = cc.GetResult(total);
showTex.text = "当前价格:" + total.ToString();
}
}
abstract class CashSuper
{
//现金收取父类,收取现金,参数为原价,返回打折后的价
public abstract float acceptCash(float money);
}
class CashNromal : CashSuper
{
public override float acceptCash(float money)
{
return money;
}
}
class CashRebate : CashSuper
{
private float moneyRebate = 1f;
public CashRebate(float moneyRebate)
{
this.moneyRebate = moneyRebate;
}
public override float acceptCash(float money)
{
return moneyRebate * money;
}
}
class CashReturn : CashSuper
{
private float moneyCondition = 0.0f;
private float moneyReturn = 0.0f;
public CashReturn(float moneyCondition, float moneyReturn)
{
this.moneyCondition = moneyCondition;
this.moneyReturn = moneyReturn;
} public override float acceptCash(float money)
{
float result = money;
if (money >= moneyCondition)
{
result = money - Mathf.Floor((float)money / moneyCondition) * moneyReturn;
}
return result;
} //Context
public class CashContext
{
private CashSuper cs;
public CashContext(string type)
{
switch (type)
{
case "正常收费":
cs =new CashNromal();
break;
case "满300反100":
cs = new CashReturn(300, 100);
break;
case "打八折":
cs = new CashRebate(0.8f);
break;
default:
break;
}
}
public float GetResult(float money)
{
return cs.acceptCash(money);
}
}
}
是不是觉得跟简单工厂模式挺像的~~让我们看一看他们有什么区别(感觉基本一样啊= =)
简单工厂模式客户端认识两个类,CashSuper和CashFactor【设计模式|由浅入深大话设计模式——策略模式】总结
策略模式只需要认识一个类CashContext即可
策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同。它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。
优点:
1.Strategy类层次为Context定义了一系列的可供重用的算法或行为。继承有助于析取出这些算法中的公共功能。
2.策略模式的优点是简化了单位测试,因为每个算法都有自己的类,可以通过自己的接口单独测试。
用法:
策略模式就是用来封装算法的,但在实践中,我们可以发现用它来封装几乎任何类型的规则,只要在分析过程中听到需要在不同时间应用不同的业务规则,就可以考虑用策略模式处理这种变化的可能性。
推荐阅读
- 设计模式|大话设计模式 —— 策略模式
- 大话设计模式——策略模式(C++实现)
- 大话设计模式|大话设计模式——第二章(策略模式JAVA版)
- 大话设计模式|大话设计模式 —— 第二章《策略模式》C++ 代码实现
- 设计模式|大话设计模式 读书笔记(二)——策略模式
- java|大话设计模式Java——策略模式
- python|关于举办“2022年(第15届)中国大学生计算机设计大赛”通知
- java设计模式|java设计模式——结构型之桥接模式
- Java设计模式|Java 设计模式--桥接模式