GOF23设计模式之策略模式(strategy)
一、策略模式概述
策略模式对应于解决某一个问题的一个算法族,允许用户从该算法族中任选一种算法解决一个问题,同时可以方便的更换算法或者增加新的算法。并且由客户端决定调用哪个算法。
策略模式的本质:
分离算法,选择实现。
二、策略模式场景导入
某公司市场部在接单时根据不同的客户进行报价,可以划分为以下几种类型:
(1)新客户小批量报价
(2)新客户大批量报价
(3)老客户小批量报价
(4)老客户大批量报价
当遇到这种情况时,可以采用策略模式实现。
三、使用普通方式实现报价操作
1 /** 2 * 普通方式实现报价 3 * @author CL 4 * 5 */ 6 public class TestStrategy { 7 8 public double getPrice(String type, double price) { 9 if (type.equals("新客户小批量")) { 10 System.out.println("不打折!"); 11 return price; 12 } 13 14 if (type.equals("新客户大批量")) { 15 System.out.println("打九折!"); 16 return price * 0.9; 17 } 18 19 if (type.equals("老客户小批量")) { 20 System.out.println("打八五折!"); 21 return price * 0.85; 22 } 23 24 if (type.equals("老客户大批量")) { 25 System.out.println("打八折!"); 26 return price * 0.8; 27 } 28 29 return price; 30 } 31 32 public static void main(String[] args) { 33 TestStrategy strategy = new TestStrategy(); 34 35 System.out.printf("您该报价:%6.2f", strategy.getPrice("老客户小批量", 998)); 36 37 System.out.println("\n---------------------------"); 38 39 System.out.printf("您该报价:%6.2f", strategy.getPrice("新客户大批量", 1024)); 40 } 41 42 }
控制台输出:
打八五折! 您该报价:848.30 --------------------------- 打九折! 您该报价:921.60
注意:实现起来很容易,符号一般开发人员的思路。但是,假如类型很多,算法比较复杂时,整个条件语句的代码就变得很长,难于维护。如果有新增类型,就需要频繁的修改代码。
不符合开闭原则!
四、使用策略模式实现报价操作
1 /** 2 * 策略模式 3 * @author CL 4 * 5 */ 6 public interface Strategy { 7 8 public double getPrice(double originalCost); 9 10 }
1 /** 2 * 新客户小批量 3 * @author CL 4 * 5 */ 6 public class NewCustomerFewStrategy implements Strategy { 7 8 @Override 9 public double getPrice(double originalCost) { 10 System.out.println("不打折!"); 11 return originalCost; 12 } 13 14 }
1 /** 2 * 新客户大批量 3 * @author CL 4 * 5 */ 6 public class NewCustomerManyStrategy implements Strategy { 7 8 @Override 9 public double getPrice(double originalCost) { 10 System.out.println("打九折!"); 11 return originalCost * 0.9; 12 } 13 14 }
1 /** 2 * 老客户小批量 3 * @author CL 4 * 5 */ 6 public class OldCustomerFewStrategy implements Strategy { 7 8 @Override 9 public double getPrice(double originalCost) { 10 System.out.println("打八五折!"); 11 return originalCost * 0.85; 12 } 13 14 }
1 /** 2 * 老客户大批量 3 * @author CL 4 * 5 */ 6 public class OldCustomerManyStrategy implements Strategy { 7 8 @Override 9 public double getPrice(double originalCost) { 10 System.out.println("打八折!"); 11 return originalCost * 0.8; 12 } 13 14 }
1 /** 2 * 负责和具体的策略类交互 3 * 使策略模式,使具体的算法和直接的客户调用分离,使算法可以独立于客户端进行独立变化。 4 * 可以通过构造器注入策略对象的引用,也可以通过set方法注入策略对象的引用。 5 * 如果使用spring的依赖注入功能,还可以通过配置文件,动态地注入不同的策略对象,动态的切换不同的算法。 6 * @author CL 7 * 8 */ 9 public class Context { 10 11 private Strategy strategy; 12 13 //通过构造器注入 14 public Context(Strategy strategy) { 15 this.strategy = strategy; 16 } 17 18 //通过set方法注入 19 public void setStrategy(Strategy strategy) { 20 this.strategy = strategy; 21 } 22 23 public void printPrice(double originalCost) { 24 System.out.printf("您该报价:%6.2f", strategy.getPrice(originalCost)); 25 } 26 27 }
测试:
1 /** 2 * 测试策略模式 3 * @author CL 4 * 5 */ 6 public class Client { 7 8 public static void main(String[] args) { 9 Strategy strategy = new OldCustomerFewStrategy(); //老客户小批量 10 Context context = new Context(strategy); 11 12 context.printPrice(998); 13 14 System.out.println("\n---------------------------"); 15 16 Strategy strategy2 = new NewCustomerManyStrategy(); //新客户大批量 17 Context context2 = new Context(strategy2); 18 19 context2.printPrice(1024); 20 21 } 22 }
控制台输出:
打八五折! 您该报价:848.30 --------------------------- 打九折! 您该报价:921.60
五、策略模式常见开发应用场景
(1)市场系统中的报价功能;
(2)医保系统中根据不同的人缴纳不同的保险费用;
(3)…………