1.模式简介
定义一组算法,将每个算法封装起来,并且使它们之间可以相互转化。
2.主要思想
定义一个通用的问题,使用不同的算法来实现,然后将这些算法都封装在一个统一接口。
策略模式使用的就是OOP的继承和多态。
3.模式优点
- 符合开放封闭原则
- 代替if else,降低代码的耦合度
4.模式缺点
- 客户端必须知道所有的策略类,并决定使用哪个策略类
- 产生很多策略类
5.模式使用
模式使用一般结合工厂方法模式一起使用
- 定义公共方法(月卡时段计算)
/**
* 月卡时段计算
*/
public interface CardPeriodPeriodStrategy {
/**
* 计算月卡有效期的共同算法
*
* @param cardDurationDTO cardDurationDTO
* @return CardDurationVO
*/
CardDurationVO getCardPeriod(CardDurationDTO cardDurationDTO, Card card, CardCategory cardCategory);
}
- 具体实现(自然月计算)
@Component
@AllArgsConstructor
public class CardPeriodNaturalMonthStrategy extends AbstractCardPeriodService implements CardPeriodPeriodStrategy {
@Override
public CardDurationVO getCardPeriod(CardDurationDTO cardDurationDTO, Card card, CardCategory cardCategory) {
Date startDate = getStartDate(cardDurationDTO.getStartDate(), card);
Date endDate = cardDurationDTO.getEndDate();
LecentAssert.notNull(endDate, "请选择结束时间!");
LecentAssert.isTrue(startDate.before(endDate), "结束时间必须大于开始时间");
//缴费月数
int monthNum = getRenewalMonths(startDate, endDate);
BigDecimal unitPrice = getUnitPrice(monthNum, cardCategory);
return buildCardDuration(startDate, endDate, monthNum, unitPrice);
}
}
天对天计算
@Component
@AllArgsConstructor
public class CardPeriodDay2DayStrategy extends AbstractCardPeriodService implements CardPeriodPeriodStrategy {
@Override
public CardDurationVO getCardPeriod(CardDurationDTO cardDurationDTO, Card card, CardCategory cardCategory) {
Date startDate = getStartDate(cardDurationDTO.getStartDate(), card);
Integer monthNum = cardDurationDTO.getMonthNum();
LecentAssert.notNull(monthNum, "请选择缴费月数!");
Date endDate = calculateEndDate(startDate, monthNum);
BigDecimal unitPrice = getUnitPrice(monthNum, cardCategory);
return buildCardDuration(startDate, endDate, monthNum, unitPrice);
}
- 定义工厂方法
@AllArgsConstructor
@Component
public class CardPeriodHandler {
private static Map<Integer, CardPeriodPeriodStrategy> map = new ConcurrentHashMap<>();
private final CardPeriodNaturalMonthStrategy cardNaturalMonthStrategy;
private final CardPeriodDay2DayStrategy cardDay2DayStrategy;
private final CardPeriodDay2DayEarlyEndStrategy cardDay2DayEarlyEndStrategy;
private final CardPeriodManyDaysStrategy cardManyDaysStrategy;
@PostConstruct
public void init() {
map.put(CardDurationTypeEnum.DAY_2_DAY.getRenewWay(), cardDay2DayStrategy);
map.put(CardDurationTypeEnum.NATURAL_MONTH.getRenewWay(), cardNaturalMonthStrategy);
map.put(CardDurationTypeEnum.DAY_2_DAY_EARLY_END.getRenewWay(), cardDay2DayEarlyEndStrategy);
map.put(CardDurationTypeEnum.MANY_DAYS.getRenewWay(), cardManyDaysStrategy);
}
public CardPeriodPeriodStrategy getHandler(Integer renewType) {
return map.get(renewType);
}
}
- 业务类调用
@Override public CardDurationVO getTimeDuration(CardDurationDTO cardDurationDTO) { CardPeriodPeriodStrategy handler = cardPeriodHandler.getHandler(cardDurationDTO.getRenewWay()); LecentAssert.notNull(handler, "无效的续费类型"); return handler.getCardPeriod(cardDurationDTO, card, cardCategory); }