您的位置:首页 > 其它

设计模式学习笔记——策略模式

2016-02-26 00:30 507 查看

策略模式

问题:商场收银软件,根据单价和数量,得到总价。
设计思路:两个输入框,分别代表单价和数量,一个下拉框,选项有:正常,打折,满减等算法
商场有时需要正常收费,有时打折扣,有时满300送100.下面是简单工厂模式下:



所有算法的父类抽象类CashSuper:
public abstract class CashSuper {

public abstract double acceptCash(double money);

}
其下的其他子类,分别代表不同的收费方式
/**
* @author xukai 打折收费
*/
public class CashRebate extends CashSuper {

private double moneyRebate = 1d;

public CashRebate(double moneyRebate) {
this.moneyRebate = moneyRebate;
}

@Override
public double acceptCash(double money) {
return money * moneyRebate;
}

}
/**
* @author xukai 正常收费
*/
public class CashNormal extends CashSuper {

@Override
public double acceptCash(double money) {
return money;
}

}
/**
* @author xukai
* 满减收费
*/
public class CashReturn extends CashSuper {

private double moneyCondition = 0.0d;

private double moneyReturn = 0.0d;

public CashReturn(double moneyCondition, double moneyReturn) {
this.moneyCondition = moneyCondition;
this.moneyReturn = moneyReturn;
}

@Override
public double acceptCash(double money) {
double result = money;
if (money > moneyCondition) {
// 如果大于返利条件,则要减去返利值
result = money - Math.floor(money / moneyCondition) * moneyReturn;
}
return result;
}
}
工厂:根据下拉框选的不同,工厂生产不同的收费方式。
public class CashFactory {

public static CashSuper createCashAccept(String type) {
CashSuper cs = null;
switch (type) {
case "正常收费":
cs = new CashNormal();
break;
case "打八折":
cs = new CashRebate(0.8);
break;
case "满300减100":
cs = new CashReturn(300.0, 100.0);
break;
}
return cs;
}

}
使用简单工厂模式解决的是对象的创建问题,工厂包括了所有的收费方式,商场更改打折额度和返利额度非常频繁,那么就要经常扩展收费方式,从而修改工厂,需要引进新的设计模式来解决这一问题。
策略模式定义:定义了算法家族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化,不会影响到使用算法的客户。



策略模式的实现:



相比简单工厂模式,去掉了包含静态方法的工厂类,添加了CashContext收费上下文类:
public class CashContext {

private CashSuper cs;

public CashContext(CashSuper cs) {
this.cs = cs;
}

public double getResult(double money) {
return cs.acceptCash(money);
}

}

通过CashContext进行调用,假如,需要添加一个打七折的收费方式,只需要重新写一个CashRebate为0.7的类,不用改CashContext中的实现。
测试方法:
public void btn_submit(double price,double count,String type){
CashContext cc = null;
switch (type) {
case "正常收费":
cc = new CashContext(new CashNormal());
break;
case "打八折":
cc = new CashContext(new CashRebate(0.8));
break;
case "满300减100":
cc = new CashContext(new CashReturn(300.0, 100.0));
break;
}
System.out.println("总费为:" + cc.getResult(price*count));
}
这种办法相当于把收费方式由客户端进行判断使用哪个算法。

简单工厂模式和策略模式对比

1.前者在内部创建需要的对象,后者对象已经创建完毕,只是调用不同的实现方法。
2.前者进入工厂之前是不存在的,返回的是要使用的对象。后者进入之前是该对象,返回依然是该对象。
3.前者生成算法的判断由工厂决定,后者由客户端决定。
4.前者的客户端需要识别所有算法的父类CashSuper和工厂CashFactory,后者只需要识别CashContext。

简单工厂模式和策略模式结合

将对象的创建转移到CashContext中,客户端不要判断生成那个对象。
public class CashContext {

private CashSuper cs = null;

public CashContext(String type) {
switch (type) {
case "正常收费":
cs = new CashNormal();
break;
case "满300返100":
cs = new CashReturn("300", "100");
break;

case "打八折":
cs = new CashRebate("0.8");
break;

}
}

public double getResult(double money) {
return cs.acceptCash(money);
}

}
测试:
public class StrategyTest {

public static void main(String[] args) {

CashContext cc = new CashContext("打八折");
System.out.println(cc.getResult(1000));

cc = new CashContext("满300返100");
System.out.println(cc.getResult(1000));

}

}
这种结合还是有弊端,新增其他算法,必须修改CashContext的switch分支。

策略模式解析

策略模式是一种定义一系列算法的方法,从概念上来将,这些算法完成的都是相同的工作,只是实现不同。

定义算法家族,分别封装起来,让它们之间可以相互转换,此模式让算法的变化,不会影响到使用算法的客户。
策略模式的优点是简化了单元测试,因为每个算法都有自己的类,可以通过自己的接口单独测试。
*使用场景:只要在分析过程中听到需要在不同时间应用不同的业务规则,可以考虑使用策略模式处理这种变化的可能性,用来封装算法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: