如果要设计一个商场收银系统,同时具备原价、打8折、满300减100的优惠,如何设计?
简单工厂模式
使用简单工厂模式确实可以比较优美地解决当下问题。
// 工厂类
public class CashFactory {
public Cash getRealCash(String keyword) {
switch (keyword) {
case "原价":
return new CashNormal();
case "8折":
return new CashRebate();
case "满300减100":
return new CashReturn();
}
return new Cash();
}
}
// 促销类
abstract class Strategy {
public abstract double getCash(double cash);
}
class StrategyA extends Strategy {
@Override
public double getCash(double cash) {
System.out.println("StrategyA");
return cash;
}
}
class StrategyB extends Strategy {
@Override
public double getCash(double cash) {
System.out.println("StrategyB");
return cash * 0.8;
}
}
class StrategyC extends Strategy {
@Override
public double getCash(double cash) {
System.out.println("StrategyC");
int rebate = (int) (cash / 300) * 100;
return cash - rebate;
}
}
但是未来若商场的促销活动更新,如推出七折、满500减200等活动,还是要重写、重新编译促销类中的代码,违背了可维护性、灵活性也差。
策略模式
策略模式:定义算法家族,将其分别封装起来,让它们之间能相互替换;而其算法的变化不会影响到客户。
建立一个上下文类,承接客户端传来的选择营销策略的数据,调用对应策略接口,输出值。
其UML图如下所示:
- 策略类:定义所有支持的算法的公共接口
- 上下文类:用一个具体策略类来配置,维护一个对策略类的引用
- 具体策略类:封装了具体的算法或行为
代码实现如下:
// 上下文类
public class Context {
Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public double getResult(double cash) {
return strategy.getCash(cash);
}
}
// 客户端类
public class Demo {
public static void main(String stra, double cash) {
double res;
switch (stra) {
case "正常收费":
res = new Context(new StrategyA()).getResult(cash);
System.out.println(res);
break;
case "8折":
res = new Context(new StrategyB()).getResult(cash);
System.out.println(res);
break;
case "满300减100":
res = new Context(new StrategyC()).getResult(cash);
System.out.println(res);
break;
}
}
}
可发现客户端类承受了太多,若需简化客户端,则将简单工厂模式与策略模式结合,如下。
策略模式与简单工厂模式结合
// 上下文类
public class Context {
Strategy strategy;
public Context(String strategy) {
switch (strategy) {
case "正常收费":
this.strategy = new StrategyA();
break;
case "8折":
this.strategy = new StrategyB();
break;
case "满300减100":
this.strategy = new StrategyC();
break;
}
}
public double getResult(double cash) {
return strategy.getCash(cash);
}
}
// 客户端类
public class Demo {
public static void main(String stra, double cash) {
Context context = new Context("8折");
double res = context.getResult(cash);
}
}