1. 程式人生 > 程式設計 >設計模式實戰之策略模式

設計模式實戰之策略模式

概念

介面提供抽象策略方法,由實現類提供具體的策略,並在使用時能整體替換。

  • 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);
複製程式碼