策略模式把对象本身和运算规则区分开来,因此我们整个模式也分为三个部分。
- 环境类(Context):用来操作策略的上下文环境,持有一个 Strategy 的引用
- 抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
- 具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。
具体代码如下:
1、定义抽象策略接口
package com.design.pattern.strategy.strategy;
/**
* 抽象策略类
*/
public interface TravelerStrategy {
void style();
}
2、具体策略类
策略类1
package com.design.pattern.strategy.concreteStrategy;
import com.design.pattern.strategy.strategy.Strategy;
import com.design.pattern.strategy.strategy.TravelerStrategy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Slf4j
@Strategy("air")
@Component
public class AirStrategy implements TravelerStrategy {
@Override
public void style() {
log.info("乘坐飞机...");
}
}
策略类2
package com.design.pattern.strategy.concreteStrategy;
import com.design.pattern.strategy.strategy.Strategy;
import com.design.pattern.strategy.strategy.TravelerStrategy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Slf4j
@Strategy("highTrain")
@Component
public class HighTrainStrategy implements TravelerStrategy {
@Override
public void style() {
log.info("乘坐高铁...");
}
}
策略类3
package com.design.pattern.strategy.concreteStrategy;
import com.design.pattern.strategy.strategy.Strategy;
import com.design.pattern.strategy.strategy.TravelerStrategy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Slf4j
@Strategy("train")
@Component
public class TrainStrategy implements TravelerStrategy {
@Override
public void style() {
log.info("乘坐火车...");
}
}
3、自定义注解 @Strategy
package com.design.pattern.strategy.strategy;
import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Strategy {
String value();
}
4、环境类实现
package com.design.pattern.strategy.context;
import com.design.pattern.strategy.strategy.Strategy;
import com.design.pattern.strategy.strategy.TravelerStrategy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@Component
public class TravelerManager implements ApplicationListener<ContextRefreshedEvent>, ApplicationContextAware {
private ApplicationContext applicationContext;
private Map<String, TravelerStrategy> map = new HashMap<>();
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
log.info("解析策略模式");
Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(Strategy.class);
beansWithAnnotation.keySet().forEach(key -> {
Object o = beansWithAnnotation.get(key);
String value = o.getClass().getAnnotation(Strategy.class).value();
if (o instanceof TravelerStrategy) {
map.put(value, (TravelerStrategy) o);
}
});
test("air");
test("train");
}
private void test(String strategy) {
TravelerStrategy travelerStrategy = map.get(strategy);
travelerStrategy.style();
}
}
启动项目时会自动将策略封装到 map 中,根据传入的策略参数执行具体的策略,执行结果如下: