前面的文章简单的实现了策略模式。今天进阶一下。
依旧用打折的案例。普通用户八折,会员五折。
话不多说,直接上代码
1.来一个用户类的枚举
public enum UserTypeEnum {
USER,MEMBER;
}
2.接着来一个注解类
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface PersionType {
UserTypeEnum type();
}
3.策略接口
public interface PriceStrategy {
Double getPrice(PriceQuery query);
}
4.写一个抽象类,用来实现策略接口中的方法,并且将公共的前置判断逻辑放在此抽象类中(此为模板设计模式),并定义好抽象方法calcPrice()让各自的策略类中去实现
public abstract class AbstractPrice implements PriceStrategy {
@Override
public Double getPrice(PriceQuery query) {
query.setType(Optional.ofNullable(query.getType()).orElse(UserTypeEnum.USER));
// do something
return calcPrice(query);
}
public abstract Double calcPrice(PriceQuery query);
}
5各自的策略类:User(普通用户),Member(会员),都需要继承公共的模板类AbstractPrice
@PersionType(type = UserTypeEnum.MEMBER)
public class Member extends AbstractPrice {
@Override
public Double calcPrice(PriceQuery query) {
return query.getPrice()*0.5;
}
}
@PersionType(type= UserTypeEnum.USER)
public class User extends AbstractPrice {
@Override
public Double calcPrice(PriceQuery query) {
return query.getPrice()*0.8;
}
}
6.写一个工厂类,所有的策略类将注入到这个类中
public class PriceFactory {
private static final PriceFactory PRICE_FACTORY=new PriceFactory();
private final List<Class<? extends PriceStrategy>> priceStrategyList;
private PriceFactory(){
Reflections reflections=new Reflections("com.etc.demo.stage.test");
Set<Class<?>> classSet=reflections.getTypesAnnotatedWith(PersionType.class);
priceStrategyList=classSet.stream().map(c->(Class<? extends PriceStrategy>) c).collect(Collectors.toList());
}
public PriceStrategy getPriceStrategy (UserTypeEnum userTypeEnum) {
for (Class<? extends PriceStrategy> clazz:priceStrategyList){
PersionType type=clazz.getAnnotation(PersionType.class);
if (type.type().equals(userTypeEnum)){
try {
return clazz.getDeclaredConstructor().newInstance();
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
e.printStackTrace();
}
}
}
return null;
}
public static PriceFactory getInstance(){
return PRICE_FACTORY;
}
}
7.写一个上下文类,用于获取具体的策略类实例,并执行对应策略类实例的计算方法:
public class PriceContext {
public static Double getPrice(PriceQuery query){
PriceStrategy priceStrategy=PriceFactory.getInstance().getPriceStrategy(query.getType());
return priceStrategy.getPrice(query);
}
}
8.测试
学废了吗?