类的划分原则
面向对象的编程,并不是类越多越好,类的划分是为了封装,但分类的基础是抽象,具有相同功能和属性的对象的抽象集合才是类。
设计模式——策略模式(Strategy Pattern)
策略模式是对算法的包装,是把使用算法的责任和算法本身分割开,委派给不同的对象管理。
策略模式的用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。
环境(Context)角色:持有一个Strategy类的引用(上下文对象),负责和具体的策略类交互。
抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。
策略模式的功能:把具体算法从具体业务处理中独立
算法的平等性:策略算法是形同行为的不同实现
1、策略模式的本质:分离算法,选择实现
2、策略模式的优缺点:
优点:
(1)可以避免让客户端涉及到不必要接触到的复杂的和只与算法有关的数据
(2)避免使用难以维护的多重条件选择语句
(3)更好的扩展
缺点:
(1)把分支判断放回客户端,要改变需求算法时,还是要去更改客户端的程序
(2)客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类
(3)增加了对象的数目
(4)只适合扁平的算法结构
3、应用场景:
(1)出现同一个算法,有很多不同的实现的情况,可以使用策略模式把这些“不同的实现”实现成为一个算法的层次类
(2)出现抽象一个定义了很多行为的类,并且是通过多个if-else语句来选择这些行为的情况,可以使用策略模式来代替这些条件语句
收银系统的策略模式实现
UML图
代码如下:
//Cash抽象类 namespace Cashier_system_1 { abstract class CashSuper { public abstract double AcceptCash(double money); } } //Cash环境类 namespace Cashier_system_1 { class CashContext { private CashSuper cs = null; public CashContext(string method) { switch (method) { case "原价": cs = new CashNormal(); break; case "满500减100": cs = new CashReturn(500, 100); break; case "打七折": cs = new CashRebate(0.7); break; } } public double GetResult(double money) { return cs.AcceptCash(money); } } } //Cash具体方法类——原价 namespace Cashier_system_1 { class CashNormal:CashSuper { public override double AcceptCash(double money) { return money; } } } //Cash具体方法类——打折 namespace Cashier_system_1 { class CashRebate:CashSuper { private double target; public CashRebate(double target) { this.target = target; } public override double AcceptCash(double money) { return money * target; } } } //Cash具体方法类——返现 namespace Cashier_system_1 { class CashReturn:CashSuper { private double discount; private double target; public CashReturn(double target,double discount) { this.target = target; this.discount = discount; } public override double AcceptCash(double money) { double result=money; if (money >= target) { result = money - discount; } return result; } } } //窗体 namespace Cashier_system_1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) { } private void button_Click(object sender, EventArgs e) { CashContext cc = new CashContext(comboBox1.SelectedItem.ToString()); double sum = cc.GetResult(Convert.ToDouble(textBox1.Text) * Convert.ToDouble(textBox2.Text)); listBox1.Items.Add("单价:" + textBox1.Text + " 数量:" + textBox2.Text + " 总价:" + sum); } private void button_Clean_Click(object sender, EventArgs e) { textBox1.Text = ""; textBox2.Text = ""; listBox1.Items.Clear(); } } }
运行窗体如下:
收银系统的简单工厂模式+策略模式实现
UML图
策略模式与简单工厂模式客户端代码对比
简单工厂模式的用法:
CashSuper csuper=CashFactory.createCashAccept(cbxType.SelectedItem.ToString());
···=csuper.acceptCash(···)
策略模式与简单工厂模式结合的用法:
CashSuper csuper=new CashContext(cbxType.SelectedItem.ToString());
···=csuper.GetResult(···)
简单工厂模式需要让客户端认识两个类,改进的策略模式只需要让客户端认识一个类。耦合度更加降低了。