涉及知识点:
枚举+枚举配置抽象类
函数式接口
设计模式
策略模式
模板方法
工厂模式
单例模式
代码实例
- 策略模式,定义抽象接口,不同的实现类实现不同的策略
- 模板方法,定义一个模板方法,把公共流程写在模板方法中,然后不同的子类按需实现模板方法流程中的方法
- 单例和工厂是按需
/** 策略业务接口 */
public interface AwardStrategy {
/**
* 奖励发放接口
*/
Map<String, Boolean> awardStrategy(String userId);
/**
* 获取策略标识,即不同渠道的来源标识
*/
String getSource();
}
定义奖励发放模板流程:
/** 定义奖励发放模板流程 */
public abstract class BaseAwardTemplate {
private static final Logger log = LoggerFactory.getLogger(BaseAwardTemplate.class);
//奖励发放模板方法
public Boolean awardTemplate(String userId) {
this.authentication(userId);
this.risk(userId);
return this.awardRecord(userId);
}
//身份验证
protected void authentication(String userId) {
log.info("{} 执行身份验证!", userId);
}
//风控
protected void risk(String userId) {
log.info("{} 执行风控校验!", userId);
}
//执行奖励发放
protected abstract Boolean awardRecord(String userId);
}
实现不同渠道的奖励业务:
@Slf4j
@Service
public class ToutiaoAwardStrategyService extends BaseAwardTemplate implements AwardStrategy {
/**
* 奖励发放接口
*/
@Override
public Boolean awardStrategy(String userId) {
return super.awardTemplate(userId);
}
@Override
public String getSource() {
return "toutiao";
}
/**
* 具体的业务奖励发放实现
*/
@Override
protected Boolean awardRecord(String userId) {
log.info("头条渠道用户{}奖励50元红包!", userId);
return Boolean.TRUE;
}
}
@Slf4j
@Service
public class WeChatAwardStrategyService extends BaseAwardTemplate implements AwardStrategy {
/**
* 奖励发放接口
*/
@Override
public Boolean awardStrategy(String userId) {
return super.awardTemplate(userId);
}
@Override
public String getSource() {
return "wx";
}
/***
* 具体的业务奖励发放实现
*/
@Override
protected Boolean awardRecord(String userId) {
log.info("微信渠道用户{}奖励100元红包!", userId);
return Boolean.TRUE;
}
}
定义工厂方法,对外统一暴露业务调用入口:
@Component
public class AwardStrategyFactory implements ApplicationContextAware {
private final static Map<String, AwardStrategy> MAP = new HashMap<>();
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
Map<String, AwardStrategy> beanTypeMap = applicationContext.getBeansOfType(AwardStrategy.class);
beanTypeMap.values().forEach(strategyObj -> MAP.put(strategyObj.getSource(), strategyObj));
}
/**
* 对外统一暴露的工厂方法
*/
public Boolean getAwardResult(String userId, String source) {
AwardStrategy strategy = MAP.get(source);
if (Objects.isNull(strategy)) {
throw new RuntimeException("渠道异常!");
}
return strategy.awardStrategy(userId);
}
/**
* 静态内部类创建单例工厂对象
*/
private static class CreateFactorySingleton {
private static AwardStrategyFactory factory = new AwardStrategyFactory();
}
public static AwardStrategyFactory getInstance() {
return CreateFactorySingleton.factory;
}
}
业务入口方法:
@RestController
@RequestMapping("/activity")
public class ActivityController {
@PostMapping("/reward3")
public void reward3(String userId, String source) {
AwardStrategyFactory.getInstance().getAwardResult(userId, source);
}
}
模板模式和策略模式的区别
策略模式
interface Strategy {
public int doOperation(int num1, int num2);
}
class OperationAdd implements Strategy{
@Override
public int doOperation(int num1, int num2) {
return num1 + num2;
}
}
class OperationSubtract implements Strategy{
@Override
public int doOperation(int num1, int num2) {
return num1 - num2;
}
}
class Context {
private Strategy strategy;
public Context(Strategy strategy){
this.strategy = strategy;
}
public int executeStrategy(int num1, int num2){
return strategy.doOperation(num1, num2);
}
}
模版模式
abstract class Game {
abstract void initialize();
abstract void startPlay();
abstract void endPlay();
//template method
public final void play(){
//initialize the game
initialize();
//start game
startPlay();
//end game
endPlay();
}
}
class Cricket extends Game {
void endPlay() {
System.out.println("Cricket Game Finished!");
}
void initialize() {
System.out.println("Cricket Game Initialized! Start playing.");
}
void startPlay() {
System.out.println("Cricket Game Started. Enjoy the game!");
}
}
class Football extends Game {
void endPlay() {
System.out.println("Football Game Finished!");
}
void initialize() {
System.out.println("Football Game Initialized! Start playing.");
}
void startPlay() {
System.out.println("Football Game Started. Enjoy the game!");
}
}
从上面代码可以看出:
- 策略模式通过has-a的组合方式去实现,在代码运行的时候根据传入参数来动态的确定策略
- 模板模式通过is-a的继承方式去实现,每一个子类都代表一种不同的模板实现
所以策略和模板经常跟工厂一同出现:模板的抽象和子类决定实现流程,策略在运行的时候动态决定哪一个子目标,工厂用来生产