商场收银时,如何促销,用打折还是返利,其实都是一些算法,用工厂来生成算法对象,这没有错,但算法本身只是一种策略,最重要的是这些算法是随时都可能互相替换的,就这点变化,而封装变化点是我们面向对象的一种很重要的思维方式。来看看策略模式的结构图和基本代码。
策略模式(Strategy):定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的,不会影响到使用算法的客户。
策略模式(Strategy)结构图如下:
1. 现金收费接口
2. 正常收费子类
3. 打折收费子类
4. 返利收费子类
5. 现金收费CashContext类
6. 客户端代码
具体如下:
1.现金收费接口:
public interface CashSuper {
public double exceptCash(double money);
}
2.正常收费子类:
public class CashNormal implements CashSuper{
@Override
public double exceptCash(double money) {
// TODO Auto-generated method stub
return money;
}
}
3.打折收费子类
public class CashRebate implements CashSuper{
private double moneyRebate = 1;
public CashRebate(double moneyRebate){
this.moneyRebate = moneyRebate;
}
public double exceptCash(double money) {
// TODO Auto-generated method stub
return money * moneyRebate;
}
}
4.返利收费子类
public class CashReturn implements CashSuper {
private double moneyCondition = 0;
private double moneyReturn = 0;
public CashReturn(double moneyCondition, double moneyReturn) {
this.moneyCondition = moneyCondition;
this.moneyReturn = moneyReturn;
}
public double exceptCash(double money) {
double result = money;
if (money >= moneyCondition) {
int temp=(int)(money/moneyCondition);
result = money -temp* moneyReturn;
}
return result;
}
}
5.现金收费CashContext类 客户端代码
public class CashContext {
CashSuper cashSuper;
public CashContext(CashSuper cashSuper) {
this.cashSuper = cashSuper;
}
public CashContext(String type) {
if ("正常收费".equals(type)) {
cashSuper = new CashNormal();
} else if ("满300返100".equals(type)) {
cashSuper = new CashReturn(300, 100);
} else if ("打8折".equals(type)) {
cashSuper = new CashRebate(0.8);
}
}
public double acceptCash(double money) {
return cashSuper.exceptCash(money);
}
}
6.客户端代码
public class Main {
private static double total = 0;
public static void main(String[] args) {
// TODO Auto-generated method stub
consume("正常收费", 1, 1000);
consume("满300返100", 1, 1000);
consume("打8折", 1, 1000);
System.out.println("总计:" + total);
}
public static void consume(String type, int num, double price) {
CashContext cashContext = new CashContext(type);
double totalPrices = cashContext.acceptCash(num * price);
total += totalPrices;
System.out.println("单价:" + price + " 数量:" + num + "合计:" + totalPrices);
}
}
回过头来反思一下策略模式,策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法与使用算法之间的耦合。
策略模式的Strategy类层次为Context定义了一系列的可供重用的算法或行为。继承有助于析取出这些算法中的公共功能。对于打折、返利或者其他的算法,其实都是对实际商品收费的一种计算方式,通过继承,可以得到它们的公共功能。
优点:
1.简化了单元测试,因为每个算法都有自己的类,可以通过自己的接口单独测试。
2.每个算法可保证它没有错误,修改其中任一个时也不会影响其他的算法,这真是的非常的好。
缺点:
1.必须知道所有策略类,这一问题可以由工厂模式加以解决。
2.产生很多策略类,这一问题可以使用享元模式加以解决。