设计模式 - 策略模式
类图
解析
-
策略模式是一种定义一系列算法的方法, 从概念上看, 所有的这些算法完成的都是相同的工作, 只是实现不同. 他可以用同样的方式调用任意的一个算法, 减少了算法类与使用算法类之间的耦合.
-
策略模式中的
Strategy
类层为Context
定义了一系列可供重用的算法或行为. 继承有处于析取这些算法中的公共功能. -
简化了单元测试, 因为每个算法都有自己的类, 可以通过自己的接口单独测试.
-
只要在分析的过程中听到需要在不同时间应用不同的业务规则, 就可以考虑使用策略模式处理这种变化的可能性.
例子
场景: 超市收银机, 有不同的优惠策略.
定义打折类
public abstract class Discount {
public abstract double algorithm(double money);
}
定义三个具体的优惠策略: 1) 不打折, 2) 打X折, 3) 满XXX返XXX
public class DiscountNormal extends Discount {
@Override
public double algorithm(double money) {
return money;
}
}
public class DiscountRebate extends Discount {
private double debate = 1d;
public DiscountRebate(double debate) {
this.debate = debate;
}
@Override
public double algorithm(double money) {
return money*debate;
}
}
public class DiscountReturn extends Discount {
private double conditionMoney;
private double returnMoney;
public DiscountReturn(double conditionMoney, double returnMoney) {
this.conditionMoney = conditionMoney;
this.returnMoney = returnMoney;
}
@Override
public double algorithm(double money) {
return money - Math.floor(money/conditionMoney)*returnMoney;
}
}
定义Context类
public class CashierContext {
private Discount discount;
public CashierContext(Discount discount) {
this.discount = discount;
}
public double getResult(double money) {
return this.discount.algorithm(money);
}
}
客户端
import java.util.Scanner;
public class ClientMain {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int strategy = 1;
double input = 0.0d;
Discount algorithm = null; // 策略的具体实现要由客户端程序员完成
try {
System.out.print("选择打折方式:\n1: 不打折\n2: 打八折\n3: 满200返20\n> ");
strategy = scanner.nextInt();
System.out.print("输入金额: ");
input = scanner.nextDouble();
} catch (Exception e) {
System.out.println("您的输入有误.");
}
switch (strategy) { //客户端程序员任然有选择的压力
case (1):
algorithm = new DiscountNormal();
break;
case (2):
algorithm = new DiscountRebate(0.8);
break;
case (3):
algorithm = new DiscountReturn(200, 20);
break;
}
System.out.println("最终金额: " + (new CashierContext(algorithm).getResult(input))); // Context 类也要由客户端完成.
}
}
在这个程序中, 客户端程序员编写分流的代码. 在现在的基础上使用简单工厂模式便可以消除分流的代码.
定义工厂上下文类
public class CashierFactoryContext {
Discount algorithm = null;
public CashierFactoryContext(int strategy) {
switch (strategy) { //客户端程序员任然有选择的压力
case (1):
this.algorithm = new DiscountNormal();
break;
case (2):
this.algorithm = new DiscountRebate(0.8);
break;
case (3):
this.algorithm = new DiscountReturn(200, 20);
break;
}
}
public double getResult(double money) {
return this.algorithm.algorithm(money);
}
}
客户端程序
import java.util.Scanner;
public class FactoryClientMain {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int strategy = 1;
double input = 0.0d;
try {
System.out.print("选择打折方式:\n1: 不打折\n2: 打八折\n3: 满200返20\n> ");
strategy = scanner.nextInt();
System.out.print("输入金额: ");
input = scanner.nextDouble();
} catch (Exception e) {
System.out.println("您的输入有误.");
}
System.out.println("最终金额: " + (new CashierFactoryContext(strategy).getResult(input)));
}
}