设计模式 - 策略模式

241 阅读2分钟

​ 我们是否在开发中遇见过一堆的if条件来判断处理各种情况 , 有些人可能会说使用switch语句哇 , 但是我们知道switch语句会出现很多问题, 有可能是类型支持不够多,或者维护太不方便,这就是引入了策略模式, 其实根据不同来采取不同的策略就是策略模式

简单的来个例子

我们现在有一个事件 , ChatEvent , 但是事件类型有很多 , 比如连接服务器事件, 接收信息时间, 异常事件, 断开服务器事件 , 还有很多事件, 但是我们如果采用if语句进行判断, 确实很难维护,代码感官不好

下面演示常见模拟

ChatEvent 事件

public interface ChatEvent {
    
    // 枚举
    ChatEventType eventType();
    
    default Object event() {
        return NULL;
    }
}

ChatEventListener 事件监听器

public interface ChatEventListener extends EventListener {
    void onChatEvent(ChatEvent event) throws Exception;
}

ChatEventHandler 事件处理器

public interface ChatEventHandler {
    void handler(ChatEvent event) throws HandlerException;
}

此时我们可能是 ChatEventType是枚举类型,是事先声明好的, 对于这种事件类型, 还是根据约定走, 因为越随意越不好维护 . 或者你可以换成枚举类型

ChatEventListener listener = new ChatEventListener() {

    @Override
    public void onChatEvent(ChatEvent event) throws Exception {

        if (event.eventType()== ChatEventType.CLIENT_SHUTDOWN) {
			//do
        }

        if (event.eventType()== ChatEventType.CLIENT_START){
			//do
        }

        if (event.eventType()== ChatEventType.CLIENT_READ){
			// do
        }

    }
};


listener.onChatEvent(ChatEvent.SERVER_START);

我们发现一堆if else, 或者 switch .. case语句时让别人看源码发现 , 这个水平也太垃圾了吧 , 就这么写 , 哎 , 所以此时我们就引入了我们的

ChatEventHandler 接口类 , 我们将他实现成各种事件的Handler , 比如 ClientReadChatEventHandler , ClientShutDownChatEventHandler 等等之类的 .

此时我们只需要维护我们这些拓展的ChatEventHandler 的实现类 , 那么我们怎么维护呢, 此时我们选择Java提供的 HashMap , 此时我们只需要一个这个就行了

public final class ClientChatHandlerConstant {

    private static final Map<ChatEventType, ChatEventHandler> HANDLER_MAP = new HashMap<>();

    static {
        // 读
        HANDLER_MAP.put(ChatEventType.CLIENT_READ, new ClientReadChatEventHandler());

        // 关闭
        HANDLER_MAP.put(ChatEventType.CLIENT_SHUTDOWN, new ClientShutDownChatEventHandler());

        // 启动
        HANDLER_MAP.put(ChatEventType.CLIENT_START, new ClientStartChatEventHandler());

        // 连接成功
        HANDLER_MAP.put(ChatEventType.CLIENT_CONNECTED, new ClientConnectedChatEventHandler());
    }

    public Map<ChatEventType, ChatEventHandler> getHandlerMap() {
        return HANDLER_MAP;
    }
}

此时我们的代码会变成

ChatEventListener listener = event -> {
    // 获取Handler
    ChatEventHandler handler = ClientChatHandlerConstant.getHandlerMap().get(event.eventType());
    // 然后处理
    handler.handler(event);
};

// 
listener.onChatEvent(ChatEvent.SERVER_START);

此时我们只需要拓展我们的handler , 就可以实现, 各种情况, 这种对于整体的拓展性也提高了, 同时代码的耦合度也大大降低 ,我们只需要维护我们的EventType , Map , EventHandler 三者关系 , 中间只有Map进行桥接 , 这就是桥接模式, 同时我们的拓展点只是我们的各种Handler 就行了 .