项目结构:
Core类库为基本类库。
CashNormal、CashReturn、CashRobate引用Core类库。
CashContext同时引用Core和CashNormal、CashReturn、CashRobate。在此类库下的CashContext类中生成对象,调用方法。
策略模式只引用CashContext类库,这个模式的好处是和基类分离,只引用一个工厂类就可以了。更高的低耦合。
代码:
Core类库 CashSuper类 namespace Core { public class CashSuper { public virtual double AcceptCash(double money) { return 0; } } } CashNormal类 namespace CashNormal { public class CashNormal:CashSuper { public override double AcceptCash(double money) { return money; } } } CashReturn类 namespace CashReturn { public class CashReturn:CashSuper { private double moneyCondition=0.0d; private double returnMoney = 0.0d; public CashReturn(double moneyCondition, double returnMoney) { this.moneyCondition = moneyCondition; this.returnMoney = returnMoney; } public override double AcceptCash(double money) { return money - returnMoney; } } } CashRobate类 namespace CashRobate { public class CashRobate:CashSuper { private double robate=1d; public CashRobate(double robate) { this.robate = robate; } public override double AcceptCash(double money) { return money * robate; } } } 策略和工厂结合类 namespace CashContext { public class CashContext { CashSuper super = null; public CashContext(int type) { switch (type) { case 1: CashNormal.CashNormal ca = new CashNormal.CashNormal(); super = ca; break; case 2: CashRobate.CashRobate ca1 = new CashRobate.CashRobate(0.8); super = ca1; break; case 3: CashReturn.CashReturn ca2 = new CashReturn.CashReturn(300, 100); super = ca2; break; } } public double GetResult(double money) { return super.AcceptCash(money); } } } 客户端调用 static void Main(string[] args) { CashContext.CashContext ca = new CashContext.CashContext(1); Console.WriteLine(ca.GetResult(100)); Console.ReadLine(); }
策略模式和工厂模式有很多相似的地方,下面是对两种模式的一些理解和网上的一些回答:
1、策略模式注重的是行为的封装。关注行为的选择
工厂模式注重的是对象模型的封装。关注对象创建
2、工厂模式需要得到的是对象。
策略模式需要的到的是结果。比如上个例子中返回的是最终的钱数。
3、策略模式就是定义一系列的算法,这些算法可以在需要的时候替换和扩展。
工厂模式是生成型的模式,在你需要的时候构建具体的实例.
4、工厂模式只需的到对象即可,而不关心内部的逻辑。
策略模式则需要客户指定行为,也就是说如何实现需要自己决定。
工厂相当于黑盒子,策略相当于白盒子
上面的例子在书中也提到了一个不足,就是当需要添加一中新的收费方式的时候,这时即需要添加一个新的支付类,并在CashContext中添加一个新的判断,指定这个新的支付类,还要在客户端添加一个类型。
这样实在很麻烦,解决上面的问题需要用到反射,大概是在config文件中配置需要引用的dll,然后在工厂类中利用反射得到config中对应的dll,
这样如果再次添加新的类,只需修改config中的节点指定到新添加的dll就可以了。而工厂类和客户端几乎不要任何修改。