面向对象的编程,并不是类越多越好,类的划分是为了封装,分类的基础是抽象,具有相同属性和功能的对象的抽象集合才是类。如商场的打一折和打九折,虽然形式上不同,但是抽象出来的算法是一样的。
策略模式:定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化不会影响到使用算法的客户。
以超市的收银软件为例:
现金收费方式类(CashPayMentMethod):
namespace CashierTest.Class { abstract class CashPayMentMethod { public abstract double acceptCashMethod(double money); } }
正常收费类(CashNormal):继承于现金收费方式类(CashPayMentMethod)
namespace CashierTest.Class { class CashNormal : CashPayMentMethod { public override double acceptCashMethod(double money) { return money; } } }
打折收费类(CashDisCountsCashBack
namespace CashierTest.Class { class CashDisCounts : CashPayMentMethod { private double moneyDiscounts = 1d; public CashDisCounts(double moneyDisCounts) { this.moneyDiscounts = moneyDisCounts; } public override double acceptCashMethod(double money) { return moneyDiscounts * money; } } }
返利收费类:(CashBack):继承于现金收费方式类(CashPayMentMethod)
namespace CashierTest.Class { class CashBack : CashPayMentMethod { //返现 private double moneyFullCash = 0.0d; //满多少钱 private double moneyBackCash = 0.0d; //反多少钱 public CashBack(double moneyFull, double moneyBack) { this.moneyFullCash = moneyFull; this.moneyBackCash = moneyBack; } public override double acceptCashMethod(double money) { double result = money; double cashBackTotal = 0.0d; while (result > moneyFullCash) { cashBackTotal += moneyBackCash; result = result - moneyFullCash; } return money - cashBackTotal; //返回实际交的金额 } } }
现金上下文类(CashContext):配置和维护对现金收费方式类(CashPayMentMethod)对象的引用。策略模式与简单工厂模式相结合
namespace CashierTest.Class { class CashContext { CashPayMentMethod cpmm; //付款方式 /// <summary> /// 简单工厂模式和策略模式相结合 /// </summary> /// <param name="type">付款方式</param> public CashContext(string type) { switch(type) { case "正常收费": CashNormal cn = new CashNormal(); cpmm = cn; break; case "满300返100": CashBack cb = new CashBack(300,100); cpmm = cb; break; case "打八折": CashDisCounts cdc = new CashDisCounts(0.8); cpmm = cdc; break; } } public double GetResult(double money) { return cpmm.acceptCashMethod(money); } } }
客户端代码:
namespace CashierTest { public partial class Form1 : Form { public Form1() { InitializeComponent(); } double result = 0.0d; private void Form1_Load(object sender, EventArgs e) { cbxCalculation.Items.AddRange(new object[] { "正常收费", "打八折", "满300返100" }); cbxCalculation.SelectedIndex = 0; } private void btnSubmit_Click(object sender, EventArgs e) { //简单工厂和策略模式相结合 double totalPrice = 0.0d; CashContext context = new CashContext(cbxCalculation.SelectedItem.ToString()); totalPrice = context.GetResult(Convert.ToDouble(txtUnitPrice.Text) * Convert.ToDouble(txtCount.Text)); result = result + totalPrice; lbxList.Items.Add("单价:" + txtUnitPrice.Text + " 数量:" + txtCount.Text + " 计算方式:" + cbxCalculation.SelectedItem + " 总计:" + totalPrice); lblTotalResult.Text = result.ToString(); } } }
策略模式结束!