一、概念
策略模式(Strategy):它定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法的变化不会影响到使用算法的客户。(原文:The Strategy Pattern defines a family of algorithms,encapsulates each one,and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.)
图1 策略模式类图
优点:
1、 简化了单元测试,因为每个算法都有自己的类,可以通过自己的接口单独测试。 2、 避免程序中使用多重条件转移语句,使系统更灵活,并易于扩展。 3、 遵守大部分GRASP原则和常用设计原则,高内聚、低偶合。
缺点: 1、 因为每个具体策略类都会产生一个新类,所以会增加系统需要维护的类的数量。 2、 在基本的策略模式中,选择所用具体实现的职责由客户端对象承担,并转给策略模式的Context对象。(这本身没有解除客户端需要选择判断的压力,而策略模式与简单工厂模式结合后,选择具体实现的职责也可以由Context来承担,这就最大化的减轻了客户端的压力。)
参考阅读: 1. 2.
二、我的理解
其实这个策略模式和简单工厂模式一样,仅仅是对面向对象继承中常用的Override技术的一种应用。简单工厂模式中有一个工厂类,负责根据输入参数的不同来生成不同的子类,并将生成的子类作为基类返回(这样可以让客户端在使用的时候很方便)。客户端只需要调用工厂类创建一个基类的实例,然后调用这个实例的函数来实现自己的功能。而策略模式中的Context类的功能基本上就是对工厂类的强化版本,它也负责根据输入参数来生成不同的类,只是它并不返回生成类,而是将生成类所实现的功能接口包装一次,提供给客户。这样对客户来说,他们只需要知道这一个Context类就可以完成他们想要的功能,而不必再知道其他的信息。
三、策略模式与简单工厂模式结合的代码实现
下面以一个简单的商场收银系统为例,演示一下策略模式与简单工厂模式结合的使用。我将这个系统用两个工程实现。一个工程实现商场计费的业务功能,另一个工程用于实现POS机上的界面,也就是客户端。
首先介绍第一个工程:
1. 实现计费功能的基类(这里用抽象类实现):
Code 1 namespace ColinSong.DesignPattern.Strategy2 {3 public abstract class BillingAlgorithm4 {5 public abstract double getBillingResult(double price, int quantity);6 }7 }2. 实现具体计费功能的子类:
2.1 实现打折计费的子类:
Code 1 namespace ColinSong.DesignPattern.Strategy 2 { 3 public class BillingStrategy_Rebate:BillingAlgorithm 4 { 5 double discounts; 6 public BillingStrategy_Rebate(double discounts) 7 { 8 if (discounts < 0.0000001 || discounts >= 1) 9 {10 this.discounts = 1;11 }12 else13 {14 this.discounts = discounts;15 }16 }17 18 public override double getBillingResult(double price, int quantity)19 {20 return price * quantity * discounts;21 }22 }23 }2.2 实现返现计费功能的子类:
Code 1 namespace ColinSong.DesignPattern.Strategy 2 { 3 public class BillingStrategy_CashReturn:BillingAlgorithm 4 { 5 int CashCondition; 6 int CashReturn; 7 public BillingStrategy_CashReturn(int CashCondition, int CashReturn) 8 { 9 if (CashCondition <= 0)10 {11 CashCondition = 1;12 }13 if (CashReturn <= 0)14 {15 CashReturn = 1;16 }17 this.CashCondition = CashCondition;18 this.CashReturn = CashReturn;19 }20 21 public override double getBillingResult(double price, int quantity)22 {23 double orignal = price * quantity;24 int n = (int) (orignal / CashCondition);25 return orignal - CashReturn * n;26 }27 }28 }293. Context类
Code 1namespace ColinSong.DesignPattern.Strategy 2{ 3 public class Billing 4 { 5 //维护一个算法基类的实例 6 BillingAlgorithm billingAlgorithm; 7 8 //简单工厂模式的构造函数 9 public Billing(string BillingStrategy)10 {11 switch (BillingStrategy)12 {13 case "打8折":14 billingAlgorithm = new BillingStrategy_Rebate(0.8);15 break;16 case "满200返40":17 billingAlgorithm = new BillingStrategy_CashReturn(200, 40);18 break;19 default:20 billingAlgorithm = new BillingStrategy_Rebate(1);21 break;22 }23 }24 //策略模式的构造函数25 public Billing(BillingAlgorithm billingAlgorithm)26 {27 this.billingAlgorithm = billingAlgorithm;28 }29 //这是策略模式的典型特征30 public double GetResult(double price, int quantity)31 {32 return billingAlgorithm.getBillingResult(price, quantity);33 }34 }35}36
好,算法完成了,下面介绍客户端,界面如图2所示:
图2. 商场收银系统界面
下面看一下,确定按钮后面的代码:
Code private void btnOK_Click(object sender, EventArgs e) { \\只需要知道这个Context类,实例化它; Billing billing = new Billing(cbxBillingType.Text); \\并调用它提供的方法,即可完成我们需要的功能。 double charge = billing.GetResult(double.Parse(txtPrice.Text), int.Parse(txtQuantity.Text)); totalCash = totalCash + charge; string itemShow = "单价:"+txtPrice.Text + "\t数量:"+txtQuantity.Text + ".\t实收:"+ charge.ToString() + "\t"+cbxBillingType.Text; list.Items.Add(itemShow); lblSum.Text = totalCash.ToString(); }
Over。O(∩_∩)O
当当网买书,价格更低,送货上门,货到付款.
转载于:https://www.cnblogs.com/colinsong/archive/2009/03/02/1401723.html
