引入问题:要实现一个商场收费软件,根据单价,数量来向客户收费,其中收费方式可以有多种(变化多)。
方法一:简单工厂模式实现
一个CashSuper类统一接口,多个具体的计算类继承于CashSuper类,一个工厂方法CashFactory创建具体实现类。

//现金收费抽象类
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 moneyRebate*money;
}
}
//返利收费
class CashReturn:CashSuper
{
private double moneyCondition = 0.0d;
private double moneyReturn = 0,0d;
public CashReturn(String moneyCondition,String moneyReturn)
{
this.moneyReturn = double.Parse(moneyReturn);
this.moneyCondition = double.Parse(moneyCondition);
}
public override double acceptCash(double money)
{
double res = money;
if(money >= moneyCondition){
res = money - Math.Floor(money/moneyCondition)*moneyReturn;
}
return res;
}
}
//工厂类
class CashFactory
{
public static CashSuper createCashAccept(String type)
{
CashSuper cs = null;
switch(type)
{
case "正常收费":
cs = new CashNormal();
break;
case "八折":
CashRebate cr1== new CashRebate("0.8")
cs = cr1;
break;
case "满三百送一百":
CashReturn cr2 = new CashReturn("300","100")
cs = cr2;
break;
}
return cs;
}
}
此时要想增加一个积分算法,如满一百积分10分,积分可兑换礼品,则加一个积分算法,传两参数(条件,返点),让它继承CashSuper,在到收费对象生成的工厂添加分支即可。
以上虽然实现了,但是商场经常性地更改打折额度和返利额度,每次维护都要改动这个工厂导致代码要重新编译部署,所以解决面对算法会时常变动的情况下,策略模式就出来解决了这个问题。
策略模式:定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。(封装变化点)

context上下文,用一个ConcreteStrategy来配置维护一个对Strategy对象的引用。
//抽象算法类,定义了所以支持算法的公共接口
abstract class Strategy
{
public abstract void AlgorithmInterface();
}
//ContreteStrategy封装了具体算法行为,继承于Strategy
class ContreteStrategyA : Strategy
{
public override void AlgorithmInterface()
{
Console.WriteLine("A实现")
}
}
class ContreteStrategyB : Strategy
{
public override void AlgorithmInterface()
{
Console.WriteLine("B实现")
}
}
class ContreteStrategyC : Strategy
{
public override void AlgorithmInterface()
{
Console.WriteLine("C实现")
}
}
//Context,用一个ConcreteStrategy来配置,维护一个对Strategy对象的引用
class Context
{
Strategy st;
public Context(Strategy st)
{
this.st = st;
}
//接口
public void ContextInterface()
{
Strategy.AlgorithmInterface();
}
}
//客户端
static void Main(string[] args)
{
Context context;
context = new Context(new ContreteStrategyA());
context.ContextInterface();
Context context;
context = new Context(new ContreteStrategyB());
context.ContextInterface();
Context context;
context = new Context(new ContreteStrategyC());
context.ContextInterface();
Console.Read();
}
方法二:
只需在方法一中加一个CashContext类并改写客户端代码就行:
class CashContext
{
private CashSuper cs;
public CashContext(CashSuper cs)
{
this.cs = cs;
}
public double GetResult(double money)
{
return cs.acceptCash(money);
}
}
CashContext cs = null;
switch(type)
{
case "正常收费":
cs = new CashContext(new CashNormal());
break;
case "":
.
.
.
}
double res = cs.GetResult();
用策略与简单工厂结合改造,把客户端判断的过程转移实现隐藏:
来源:https://www.cnblogs.com/rat-bin/p/4101447.html
