设计模式——策略模式2
本文的特点在于使用反射技术消除了if-else语句的使用。
一、概述
1、策略模式定义一系列的算法,并将每一个算法封装起来, 并且使它们以在运行时更改。这种类型的设计模式属于行为型模式。
2、优点
- 算法可以*切换。
- 避免使用多重条件判断。(更确切的说是将多重判断转移到别的地方,比如转移到Client中,或者限定输入的格式)
- 扩展性良好。
3、缺点
- 策略类会增多。
- 所有策略类都需要对外暴露。
二、绘制UML类图
在idea中使用PlantUML插件绘制UML类图。使用简单工厂创建具体策略类。
@startuml 'https://plantuml.com/class-diagram abstract class DiscountStrategy{ + double calculate(double consumeAmount) } class VipStrategy1{ + double calculate(double consumeAmount) } class VipStrategy2{ + double calculate(double consumeAmount) } class Factory{ - DiscountStrategy discountStrategy; - String strategyFullName; + Factory setVipClass(int vipClass) + Factory createStrategy() + double getVipPrice(double originPrice) } DiscountStrategy <|.. VipStrategy1 DiscountStrategy <|.. VipStrategy2 Factory "1" o--> "1" DiscountStrategy
'Factory中有一个DiscountStrategy类型的成员变量,所以使用关联关系 '又因为是在不是在普通函数中进行DiscountStrategy对象的初始化所以使用聚合关系。 '如果在构造函数中进行DiscountStrategy对象的初始化则使用组合关系 '如果DiscountStrategy对象以方法参数形式出现则使用一般关联关系 @enduml
三、代码实现
目录结构:
1、定义策略接口
/** * @author QinJiaYing * @description * @date 2021/11/10 10:51 */ public interface DiscountStrategy { public double calculate(double consumeAmount); }
2、定义具体策略类
/** * @author QinJiaYing * @description * @date 2021/11/10 10:54 */ public class VipStrategy1 implements DiscountStrategy { @Override public double calculate(double consumeAmount) { return consumeAmount*0.95; } }
/** * @author QinJiaYing * @description * @date 2021/11/10 10:57 */ public class VipStrategy2 implements DiscountStrategy{ @Override public double calculate(double consumeAmount) { return consumeAmount*0.9; } }
3、定义创建策略的工厂类
public class Factory { private DiscountStrategy discountStrategy; private String strategyFullName; public Factory() { } public Factory setVipClass(int vipClass) { strategyFullName = "练习.strategy.mystrategy.VipStrategy" + vipClass; return this; } public Factory createStrategy() { try { Class c = Class.forName(strategyFullName); this.discountStrategy = (DiscountStrategy) c.newInstance(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return this; } public double getVipPrice(double originPrice) { return discountStrategy.calculate(originPrice); } }
4、测试
/** * @author QinJiaYing * @description * @date 2021/11/10 11:07 */ public class Demo { public static void main(String[] args) { Factory factory =new Factory(); System.out.println(factory.setVipClass(1).createStrategy().getVipPrice(200)); System.out.println(factory.setVipClass(2).createStrategy().getVipPrice(200)); } }
5、运行结果
7、总结
使用反射消除了if-else语句。但需要对用户输入进行严格限定,输入vip等级的时候,必需是vip等级数值。更具体地说,要使得strategyFullName 是相应策略类的全限定类名
strategyFullName = "练习.strategy.mystrategy.VipStrategy" + vipClass;
四、参考链接
- 《大话设计模式》
- 菜鸟教程——策略模式