由浅入深大话设计模式——策略模式

9 篇文章 2 订阅
7 篇文章 0 订阅

这次我们依旧是从一个简单的小问题开始~鉴于本人不会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.策略模式的优点是简化了单位测试,因为每个算法都有自己的类,可以通过自己的接口单独测试。

用法:

    策略模式就是用来封装算法的,但在实践中,我们可以发现用它来封装几乎任何类型的规则,只要在分析过程中听到需要在不同时间应用不同的业务规则,就可以考虑用策略模式处理这种变化的可能性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 《设计模式之禅第3版pdf》是一本介绍设计模式的书籍,是作者秦小波总结多年编程和软件开发实践的经验而得出的结论。该书提供了许多实用的设计模式,这些模式可以帮助开发人员更好地编写可维护、可扩展和可重用的代码。 该书首先介绍了设计模式的基本概念和原则,例如SOLID原则和GRASP原则,然后详细介绍了23种常见的设计模式,包括创建型、结构型和行为型模式。 该书的优点在于,它不仅提供了许多具体的代码示例和实际应用场景,还深入解释了每个模式的原理和适用条件。此外,该书还提供了设计模式的演化历程,以及如何使用UML图形表示不同的模式。 虽然该书提供了丰富的知识,但它并不是一本初学者可以轻松掌握的书籍。初学者可能需要花费很多时间和精力来理解书中的概念和代码实例。与此同时,该书的代码示例使用Java语言,因此对于非Java开发人员可能需要适当地进行转换。 综上所述,《设计模式之禅第3版pdf》是一本非常有价值的设计模式书籍,对于希望提高代码质量和扩展性的开发人员来说,是一本必读之作。 ### 回答2: 《设计模式之禅第3版》是一本关于对象设计模式的经典著作,是程序员学习设计模式的一本不可或缺的参考书。该书共分为3部分,包含了23种设计模式,并以生动的例子和详细的代码展示了如何应用各种设计模式解决实际问题。 第一部分介绍了7种创建型模式,这些模式主要用于创建对象。其中包括了工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式、享元模式和对象池模式。通过这一部分的学习,读者可以了解到如何灵活地创建对象,避免了对象创建过程中出现的一些问题。 第二部分介绍了11种结构型模式,这些模式主要用于组织类和对象。其中包括了适配器模式、桥接模式、组合模式、装饰器模式、外观模式、享元模式、代理模式、管道过滤器模式、私有类数据模式、模板方法模式和访问者模式。通过这一部分的学习,读者可以学会如何组织各种不同类和对象之间的关系,从而更加有条理地编写代码。 第三部分介绍了5种行为型模式,这些模式主要用于管理对象之间的交互和职责。其中包括了责任链模式、命令模式、解释器模式、迭代器模式和观察者模式。通过这一部分的学习,读者可以学会如何精确地定义对象之间的互动和职责,从而更好地解决实际问题。 总体而言,《设计模式之禅第3版》由浅入深,结构清晰,用通俗易懂的语言阐述了设计模式的本质和应用,是程序员进行设计模式学习和应用的一本宝典。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值