设计模式——策略模式(使用反射消除if-else)

设计模式——策略模式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

 

设计模式——策略模式(使用反射消除if-else)

三、代码实现

目录结构:

设计模式——策略模式(使用反射消除if-else)

 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、运行结果

设计模式——策略模式(使用反射消除if-else)

 7、总结

使用反射消除了if-else语句。但需要对用户输入进行严格限定,输入vip等级的时候,必需是vip等级数值。更具体地说,要使得strategyFullName 是相应策略类的全限定类名

strategyFullName = "练习.strategy.mystrategy.VipStrategy" + vipClass;

四、参考链接

上一篇:全面通透深入剖析工厂方法模式


下一篇:Java - 为什么Java的泛型要用“擦除“实现