大话设计模式-第02章 商场促销--策略模式
2016-06-04 00:11
369 查看
第02章商场促销--策略模式
2.1 商场收银软件
版本1:
double total = 0.0d;
private void btnOk_Click(object sender, EventArgs e)
{
double totalPrices = Convert.ToDouble(txtPrice.text) * Convert.ToDouble(txtNum.Text);
total = total + totalPrices;
lbxList.Items.Add(“单价:” + txtPrice.Text + “数量:” + txtNum.Text + “合计:” + totalPrices.ToString());
lblResult.Text = total.ToString();
}
2.2 增加打折
版本2:
private void Forml_Load(object sender, EventArgs e)
{
cbxType.Items.AddRange(new object[] {“正常收费”,“打八折”,“打七折”,“打五折”});
cbxType.SelectedIndex = 0;
}
private void btnOk_Click(object sender, EventArgs e)
{
double totalPrices = 0d;
switch (cbxType.SelectedIndex)
{
case 0:
totalPrices = Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text);
break;
case 1:
totalPrices = Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text) * 0.8;
break;
case 2:
totalPrices = Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text) * 0.7;
break;
case 3:
totalPrices = Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text) * 0.5;
break;
}
total = total + totalPrices;
lbxList.Items.Add(“单价:” + txtPrice.Text + “数量:” + txtNum.Text + “合计:” + totalPrices.ToString());
lblResult.Text = total.ToString();
}
上述代码:
1:重复代码过多;
2:如果要支持新的折扣算法,如满*返现等,则很难扩展。
2.3 简单工厂实现
面向对象的编程,并不是类越多越好,类的划分是为了封装,但分类的基础是抽象,具有相同属性和功能的对象的抽象集合才是类。
rebate |ˈriːbeɪt| noun返款、折扣
cash |kæʃ| noun
Uncountable 现金
代码3:
现金收费抽象类
abstract class CashSuper
{
public abstract double acceptCash(double money);
}
正常收费子类
class CashNormal : CashSuper
{
public override double acceptCash(double money)
{
return money;
}
}
打折收费子类
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;
}
}
返利收费子类。
class CashReturn : CashSuper
{
private double moneyCondition = 0.0d;
private double moneyReturn = 0.0d;
public CashReturn(string moneyCondition, string moneyReturn)
{
this.moneyCondition = double.Parse(moneyCondition);
this.moneyReturn = double.Parse(moneyReturn);
}
public override double acceptCash(double money)
{
double result = money;
if(money >= moneyCondition)
{
result = money - Math.Floor(money / moneyCondition) * moneyReturn;
}
return result;
}
}
现金收费工厂类
class CashFactory
{
public static CashSuper createCashAccept(string type)
{
CashSuper cs = null;
switch(type)
{
case “正常收费”;
cs = new CashNormal();
break;
case “满300返100”;
CashReturn cr1 = new CashReturn(“300”, “100”);
cs = cr1;
break;
case “打8折”;
CashRebate cr2 = new CashRebate(“0.8”);
cs = cr2;
break;
}
return cs;
}
}
客户端程序主要部分
double total = 0.0d;
private void btnOk_Click(object sender, EventArgs e)
{
CashSuper super = CashFactory.createCashAccept(cbxType.selectedItem.ToString());
double totalPrices = 0d;
totalPrices = csuper.acceptCash(Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text));
total = total + totalPrices;
lbxList.Items.Add(“单价:” + txtPrice.Text + “数量:” + txtNum.Text + “合计:” + totalPrices.ToString());
lblResult.Text = total.ToString();
}
上面的代码虽然极大的优化了代码,但仍然难以适应变化。
2.4 策略(Strategy)模式
strategy |ˈstrætədʒi| noun战略、策略
algorithm |ˈælgərɪðəm| noun算法
context |ˈkɒntekst| noun环境、上下文
策略模式(Strategy):定义了算法家族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化,不会影响到使用算法的客户。
Strategy类,定义所有支持的算法的公共接口
//抽象算法类
abstract class Strategy
{
//算法方法
public abstract void AlgorithmInterface();
}
ConcreteStrategy,封装了具体的算法或行为,继承于Strategy
//具体算法A
class ConcreteStrategyA : Strategy
{
//算法A实现方法
public override void AlgorithmInterface()
{
console.WriteLine(“算法A实现”);
}
}
//具体算法B
class ConcreteStrategyB : Strategy
{
//算法B实现方法
public override void AlgorithmInterface()
{
console.WriteLine(“算法B实现”);
}
}
//具体算法C
class ConcreteStrategyC : Strategy
{
//算法C实现方法
public override void AlgorithmInterface()
{
console.WriteLine(“算法C实现”);
}
}
Context, 用一个ConcreteStrategy来配置,维护一个对Strategy对象的引用。
//上下文
class Context
{
Strategy strategy;
public Context(Strategy strategy)
{
this.strategy = strategy;
}
//上下文接口
public void ContextInterface()
{
strategy.AlgorithmInterface();
}
}
客户端代码
static void Main(string[] args)
{
Context context;
context = new Context(new ConcreteStrategyA());
context.ContextInterface();
context = new Context(new ConcreteStrategyB());
context.ContextInterface();
context = new Context(new ConcreteStrategyC());
context.ContextInterface();
Console.Read();
}
2.5 策略模式实现
class CashContext
{
private CashSuper cs;
public CashContext(CashSuper super)
{
this.cs = csuper;
}
public double GetResult(double money)
{
return cs.acceptCash(money);
}
}
客户端主要代码
double total = 0.0d;//用于总计
private void btn0k_Click(object sender, EventArgs e)
{
CashContext cc = null;
switch (cbxType.SelectedItem.ToString())
{
case “正常收费”:
cc = new CashContext(new CashNormal());
break;
case “满300返100”:
cc = new CashContext(new CashReturn(“300”, “100”));
break;
case “打8折”:
cc = new CashContext(new CashRebate(“0.8”));
break;
}
double totalPrices = 0d;
totalPrices = cc.GetResult(Convert.ToDouble(txPrice.Text) * Convert.ToDouble(txtNum.Text));
total = total + totalPrices;
lbxList.Items.Add(“单价:” + txtPrice.Text + “数量:” + txtNum.Text + “合计:” + totalPrices.ToString());
lblResult.Text = total.ToString();
}
上面的代码也可以通过简单工厂模式把判断的过程从客户端转移走。这样客户端只需要“认识”简单工厂类即可。
2.7 策略模式解析
策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。
策略模式的抽象Strategy类层次为Context定义了一系列可供重用的算法或行为。继承有助于析取这些算法中的公共功能。另外简单工厂也简化了单元测试。
基本的策略模式中,选择所用具体实现的职责有客户端对象承担,并转给策略模式的Context对象。这本身并没有解除客户端需要选择判断的压力,而策略模式与简单工厂模式相结合后,可以大大简化客户端的职责。
但如果需要增加新的算法,依然需要对简单工厂类做修改,任何需求的变更都是需要成本的。只是成本高低有差异而已。
2.1 商场收银软件
版本1:
double total = 0.0d;
private void btnOk_Click(object sender, EventArgs e)
{
double totalPrices = Convert.ToDouble(txtPrice.text) * Convert.ToDouble(txtNum.Text);
total = total + totalPrices;
lbxList.Items.Add(“单价:” + txtPrice.Text + “数量:” + txtNum.Text + “合计:” + totalPrices.ToString());
lblResult.Text = total.ToString();
}
2.2 增加打折
版本2:
private void Forml_Load(object sender, EventArgs e)
{
cbxType.Items.AddRange(new object[] {“正常收费”,“打八折”,“打七折”,“打五折”});
cbxType.SelectedIndex = 0;
}
private void btnOk_Click(object sender, EventArgs e)
{
double totalPrices = 0d;
switch (cbxType.SelectedIndex)
{
case 0:
totalPrices = Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text);
break;
case 1:
totalPrices = Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text) * 0.8;
break;
case 2:
totalPrices = Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text) * 0.7;
break;
case 3:
totalPrices = Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text) * 0.5;
break;
}
total = total + totalPrices;
lbxList.Items.Add(“单价:” + txtPrice.Text + “数量:” + txtNum.Text + “合计:” + totalPrices.ToString());
lblResult.Text = total.ToString();
}
上述代码:
1:重复代码过多;
2:如果要支持新的折扣算法,如满*返现等,则很难扩展。
2.3 简单工厂实现
面向对象的编程,并不是类越多越好,类的划分是为了封装,但分类的基础是抽象,具有相同属性和功能的对象的抽象集合才是类。
rebate |ˈriːbeɪt| noun返款、折扣
cash |kæʃ| noun
Uncountable 现金
代码3:
现金收费抽象类
abstract class CashSuper
{
public abstract double acceptCash(double money);
}
正常收费子类
class CashNormal : CashSuper
{
public override double acceptCash(double money)
{
return money;
}
}
打折收费子类
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;
}
}
返利收费子类。
class CashReturn : CashSuper
{
private double moneyCondition = 0.0d;
private double moneyReturn = 0.0d;
public CashReturn(string moneyCondition, string moneyReturn)
{
this.moneyCondition = double.Parse(moneyCondition);
this.moneyReturn = double.Parse(moneyReturn);
}
public override double acceptCash(double money)
{
double result = money;
if(money >= moneyCondition)
{
result = money - Math.Floor(money / moneyCondition) * moneyReturn;
}
return result;
}
}
现金收费工厂类
class CashFactory
{
public static CashSuper createCashAccept(string type)
{
CashSuper cs = null;
switch(type)
{
case “正常收费”;
cs = new CashNormal();
break;
case “满300返100”;
CashReturn cr1 = new CashReturn(“300”, “100”);
cs = cr1;
break;
case “打8折”;
CashRebate cr2 = new CashRebate(“0.8”);
cs = cr2;
break;
}
return cs;
}
}
客户端程序主要部分
double total = 0.0d;
private void btnOk_Click(object sender, EventArgs e)
{
CashSuper super = CashFactory.createCashAccept(cbxType.selectedItem.ToString());
double totalPrices = 0d;
totalPrices = csuper.acceptCash(Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text));
total = total + totalPrices;
lbxList.Items.Add(“单价:” + txtPrice.Text + “数量:” + txtNum.Text + “合计:” + totalPrices.ToString());
lblResult.Text = total.ToString();
}
上面的代码虽然极大的优化了代码,但仍然难以适应变化。
2.4 策略(Strategy)模式
strategy |ˈstrætədʒi| noun战略、策略
algorithm |ˈælgərɪðəm| noun算法
context |ˈkɒntekst| noun环境、上下文
策略模式(Strategy):定义了算法家族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化,不会影响到使用算法的客户。
Strategy类,定义所有支持的算法的公共接口
//抽象算法类
abstract class Strategy
{
//算法方法
public abstract void AlgorithmInterface();
}
ConcreteStrategy,封装了具体的算法或行为,继承于Strategy
//具体算法A
class ConcreteStrategyA : Strategy
{
//算法A实现方法
public override void AlgorithmInterface()
{
console.WriteLine(“算法A实现”);
}
}
//具体算法B
class ConcreteStrategyB : Strategy
{
//算法B实现方法
public override void AlgorithmInterface()
{
console.WriteLine(“算法B实现”);
}
}
//具体算法C
class ConcreteStrategyC : Strategy
{
//算法C实现方法
public override void AlgorithmInterface()
{
console.WriteLine(“算法C实现”);
}
}
Context, 用一个ConcreteStrategy来配置,维护一个对Strategy对象的引用。
//上下文
class Context
{
Strategy strategy;
public Context(Strategy strategy)
{
this.strategy = strategy;
}
//上下文接口
public void ContextInterface()
{
strategy.AlgorithmInterface();
}
}
客户端代码
static void Main(string[] args)
{
Context context;
context = new Context(new ConcreteStrategyA());
context.ContextInterface();
context = new Context(new ConcreteStrategyB());
context.ContextInterface();
context = new Context(new ConcreteStrategyC());
context.ContextInterface();
Console.Read();
}
2.5 策略模式实现
class CashContext
{
private CashSuper cs;
public CashContext(CashSuper super)
{
this.cs = csuper;
}
public double GetResult(double money)
{
return cs.acceptCash(money);
}
}
客户端主要代码
double total = 0.0d;//用于总计
private void btn0k_Click(object sender, EventArgs e)
{
CashContext cc = null;
switch (cbxType.SelectedItem.ToString())
{
case “正常收费”:
cc = new CashContext(new CashNormal());
break;
case “满300返100”:
cc = new CashContext(new CashReturn(“300”, “100”));
break;
case “打8折”:
cc = new CashContext(new CashRebate(“0.8”));
break;
}
double totalPrices = 0d;
totalPrices = cc.GetResult(Convert.ToDouble(txPrice.Text) * Convert.ToDouble(txtNum.Text));
total = total + totalPrices;
lbxList.Items.Add(“单价:” + txtPrice.Text + “数量:” + txtNum.Text + “合计:” + totalPrices.ToString());
lblResult.Text = total.ToString();
}
上面的代码也可以通过简单工厂模式把判断的过程从客户端转移走。这样客户端只需要“认识”简单工厂类即可。
2.7 策略模式解析
策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。
策略模式的抽象Strategy类层次为Context定义了一系列可供重用的算法或行为。继承有助于析取这些算法中的公共功能。另外简单工厂也简化了单元测试。
基本的策略模式中,选择所用具体实现的职责有客户端对象承担,并转给策略模式的Context对象。这本身并没有解除客户端需要选择判断的压力,而策略模式与简单工厂模式相结合后,可以大大简化客户端的职责。
但如果需要增加新的算法,依然需要对简单工厂类做修改,任何需求的变更都是需要成本的。只是成本高低有差异而已。
相关文章推荐
- 0603 职业道德--软件工程
- Javassist简单应用总结
- Linux-netstat命令详解
- lua之函数
- Java基础回顾 : 集合类
- spring boot使用
- 第1章 入门
- 模拟一些字符串库函数(笔试常考)
- 全屏滚动图片网站制作(HTML5+JS+jQuery)——(HTML+CSS篇)
- 去除微信二维码白色背景
- Eclipse中Tomcat开启却访问404
- LeetCode--No.35--Search Insert Position
- PAT基础编程题目集--函数集4-6
- leetcode--009. Palindrome Number
- Mac 让 iTerm2 记住用户名密码 expect 脚本
- Mac 让 iTerm2 记住用户名密码 expect 脚本
- UVALive 6257 Chemist's vows 判断一个字符串是否由n中的某些字符串组成 dp
- 简单题
- Java字符有中文长度计算
- GPU(CUDA)学习日记(二)续二------ VS2010 不同工程之间调用DLL