設計模式實戰之策略模式
阿新 • • 發佈:2019-12-31
概念
介面提供抽象策略方法,由實現類提供具體的策略,並在使用時能整體替換。
- Strategy 策略介面
- ConcreteStrategy 具體策略實現類
- Context 上下文 用來選擇具體策略
適用場景
- 根據不同業務型別選擇不同的處理器來處理
- 替換大量if else
優點
- 策略之間可以隨意切換
- 新增新策略只需要新建類,不需要修改原有程式碼
缺點
- 當策略比較多時,也需要較多的實現類
實戰
根據不能訊息型別來選擇不能的訊息處理器
- 訊息實體類
@Data
public class Message {
private String type;
private String content;
}
複製程式碼
- 訊息處理介面 策略介面
public interface IMessageHandler {
/**
* 訊息處理
* @param message msg
*/
void handle(Message message) throws Exception;
/**
* 支援處理的訊息型別 text、image 等
* @return string
*/
String support();
}
複製程式碼
- 純文字訊息處理器 具體策略
/**
* 純文字訊息處理器
* @author xup
* @date 2019/11/12 19:00
*/
@Component
public class TextMessageHandler implements IMessageHandler {
@Override
public void handle(Message message) {
System.out.println("處理純文字訊息" );
}
@Override
public String support() {
return "Text";
}
}
複製程式碼
- 圖片訊息處理器 具體策略
/**
* 圖片訊息處理器
* @author xup
* @date 2019/11/12 19:01
*/
@Component
public class ImageMessageHandler implements IMessageHandler {
@Override
public void handle(Message message) {
System.out.println("處理純文字訊息" );
}
@Override
public String support() {
return "Image";
}
}
複製程式碼
- 訊息處理器路由類 策略路由類
/**
* 訊息處理器路由類
* 只進行路由,不進行訊息處理
* @author xup
* @date 2019/11/12 19:06
*/
@Order(1)
@Component
public class MessageHandlerRoute implements IMessageHandler{
/**
* 業務型別和業務處理器存放的容器
*/
private Map<String,IMessageHandler> messageHandlerMap = new HashMap<>(8);
/**
* 初始化類是 將IMessageHandler的所有實現類放入map容器
*/
@PostConstruct
public void init(){
Map<String,IMessageHandler> beanMap = SpringContextHolder.getBeansOfType(IMessageHandler.class);
for (IMessageHandler handler : beanMap.values()) {
messageHandlerMap.put(handler.support(),handler);
}
}
/**
* 根據訊息型別路由到不同的處理器
* @param message msg
* @return IMessageHandler
*/
public IMessageHandler route(Message message) throws Exception {
IMessageHandler handler = messageHandlerMap.get(message.getType());
if (handler == null){
throw new Exception("此訊息型別沒有配置處理器");
}
return handler;
}
@Override
public void handle(Message message) throws Exception {
IMessageHandler handler = route(message);
handler.handle(message);
}
@Override
public String support() {
return "null";
}
}
複製程式碼
路由類可不實現策略介面。 可通過注入路由類,然後路由到具體的處理器再進行處理
IMessageHandler handler = messageHandlerRoute.route(message)
handler.handle(message)
複製程式碼
- spring 上下文持有類
/**
* spring 上下文持有類
*
* @author xup
* @date 2019/11/12 17:45
*/
@Component
public class SpringContextHolder implements ApplicationContextAware {
private static ApplicationContext applicationContext = null;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextHolder.applicationContext = applicationContext;
}
/**
* 獲取ApplicationContext.
*/
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
/**
* 從applicationContext中得到Bean,自動轉型為所賦值物件的型別.
*/
public static <T> T getBean(Class<T> requiredType) {
return applicationContext.getBean(requiredType);
}
@SuppressWarnings("unchecked")
public static <T> T getBean(String beanName) {
return (T)applicationContext.getBean(beanName);
}
/**
* 獲取spring 容器中所有指定型別的Bean
* @param type class
* @return map
*/
public static <T> Map<String,T> getBeansOfType(Class<T> type) {
return applicationContext.getBeansOfType(type);
}
}
複製程式碼
- 實際呼叫
@Autowired
IMessageHandler messageHander;
messageHandler.hander(message);
複製程式碼