基于Spring自动注入的策略模式

一 背景:

  • 比如我现在要一个具体的活动进行crud
  • 但我的活动分成多种活动模式如:秒杀,折扣等,这样就不能统一对具体活动进行crud

二 传统方式:

  • 1,我就要通过创建不同活动类型的service如:ISeckillActivityService,IDiscountActivityService等

  • 2,在要进行crud的地方,通过活动的类型去做if判断/switch,来调用相应的service,再进行crud操作

  • 缺点: 这样代码中会有大量的if或者switch

三 解决方式

  • 基于Spring自动注入的策略模式

1> 类结构关系图

《基于Spring自动注入的策略模式》
如图:由于IDiscountActivityService 和ISeckillActivityService 都继承了BaseActivityService ,
spring提供了根据类型注入bean的特性,我们可以将同一种类型的bean注入到一个map中而具体的service(bean)的key为其id

2> 具体java类

策略模式关键类

  • BaseActivityService需要统一操作的接口方法
/**
 * @description: 活动基础service
 * @author: kismet
 * @create: 2018-10-25 11:48
 */
public interface BaseActivityService {

    /**
     * 添加活动
     * @return
     */
    Long addActivity(ActivityVo vo);
    /**
     * 更新活动
     * @return
     */
    void upDateActivity(ActivityVo vo);
}
  • IDiscountActivityService 折扣活动接口
/**
 * @description:折扣活动
 * @author: kismet
 * @create: 2018-10-25 11:50
 */
public interface IDiscountActivityService extends BaseActivityService {
}
  • ISeckillActivityService 秒杀活动接口
/**
 * @description: 秒杀活动
 * @author: kismet
 * @create: 2018-10-25 11:50
 */
public interface ISeckillActivityService extends BaseActivityService {

}
  • DiscountActivityServiceImpl 折扣活动实现类
/**
 * @description:
 * @author: kismet
 * @create: 2018-10-25 11:58
 */
@Service("discountActivityService")
public class DiscountActivityServiceImpl implements IDiscountActivityService {
    @Override
    public Long addActivity(ActivityVo vo) {
        System.out.println("折扣活动添加");
        return -1L;
    }

    @Override
    public void upDateActivity(ActivityVo vo) {
        System.out.println("折扣活动更新");
    }
}
  • SeckillActivityServiceImpl 秒杀活动实现类
/**
 * @description:
 * @author: kismet
 * @create: 2018-10-25 11:59
 */
@Service("seckillActivityService")
public class SeckillActivityServiceImpl implements ISeckillActivityService {

    @Override
    public Long addActivity(ActivityVo vo) {
        System.out.println("秒杀活动添加");
        return -2L;
    }

    @Override
    public void upDateActivity(ActivityVo vo) {
        System.out.println("秒杀活动更新");
    }
}

其他相关类

  • ActivityTypeEnum 活动类型枚举
/**
 * @description: 活动类型枚举
 * @author: kismet
 * @create: 2018-10-08 9:14
 */
@Getter
public enum ActivityTypeEnum {

    /**
     * 1,秒杀活动;service的key即为seckillActivityService
     */
    SECKILL(1, "秒杀活动", "seckillActivityService"),

    /**
     * 2,折扣活动;service的key即为discountActivityService
     */
    DISCOUNT(2, "折扣活动", "discountActivityService");

    private Integer key;

    private String desc;

    /**
     * 对应的service实现类key
     */
    private String service;

    ActivityTypeEnum(Integer key, String desc, String service) {
        this.key = key;
        this.desc = desc;
        this.service = service;
    }

    public static ActivityTypeEnum getEnumByType(Integer key) {
        for (ActivityTypeEnum item : ActivityTypeEnum.values()) {
            if (item.getKey().equals(key)) {
                return item;
            }
        }
        throw new RuntimeException("通过key获取枚举类异常");
    }
}
  • ActivityVo活动基本信息类
**
 * @description: 活动基本信息类
 * @author: kismet
 * @create: 2018-10-25 12:45
 */
@Getter
@Setter
public class ActivityVo {

    /**
     * 活动id
     */
    private Long id;
    /**
     * 活动类型:1,秒杀活动;2折扣活动
     */
    private Integer activityType;
}
  • MyTestController 测试类
/**
 * @description: 测试controller
 * @author: kismet
 * @create: 2018-10-25 12:54
 */
@RestController
public class MyTestController {

    //注入BaseActivityService子类的service,key为子类service的key
    @Autowired
    private Map<String,BaseActivityService> activityServiceMap;

    @RequestMapping("test")
    public void test(ActivityVo vo){
        vo.setActivityType(ActivityTypeEnum.SECKILL.getKey());//设置活动类型为直降测试用
        //1,根据活动对象获取活动类型,
        Integer activityType = vo.getActivityType();
        //2,获取活动对象的service的key
        String servicekey = ActivityTypeEnum.getEnumByType(activityType).getService();
        //3,获取对应的活动service
        BaseActivityService service = activityServiceMap.get(servicekey);
        //4,调用具体活动service的方法;add或者update等等
        service.addActivity(vo);
        service.upDateActivity(vo);
    }
}

测试和小结:

1> 测试

  • 当测试类中的vo的活动类型为1,秒杀活动时,
    即 vo.setActivityType(ActivityTypeEnum.SECKILL.getKey());
    控制台输出:

    秒杀活动添加
    秒杀活动更新

  • 当测试类中的vo的活动类型为1,秒杀活动时,控制台输出:
    即vo.setActivityType(ActivityTypeEnum.DISCOUNT.getKey());
    控制台输出:

    折扣活动添加
    折扣活动更新

小结:

  • 1>该策略方式借助于spring的ioc方式,将同一类型的bean注入到一个Map中
  • 2>将bean的id存到对应枚举中,
  • 3>通过活动的类型获取到具体的枚举,
  • 4>这样就可以通过枚举去得到bean的id,从而从Map中取到具体的bean
  • 5>然后再调用bean的方法
    原文作者:kismet2399
    原文地址: https://blog.csdn.net/kismet2399/article/details/83385197
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞