设计模式-策略模式在spring中的实践 | Java Debug 笔记

279 阅读3分钟

本文正在参加「Java主题月 - Java Debug笔记活动」,详情查看 活动链接

起因

在一个阳光明媚早上,沉浸在快乐摸鱼的我,突然收到leader发给我的一个需求:大致就是A系统要给MQ的一个topic写入消息,我们的B系统消费消息做业务逻辑处理。

仔细一看这不so easy,直接一顿操作,赶在下班前写完,趁着还剩余点的时间,赶紧在摸摸鱼,坐等下班。

代码逻辑:

public interface IConsumerService {

    /**
     * 消费消息
     * @param message
     * @return
     */
    boolean consumerHandler(Map<String,Object> message);
}


public class ConsumerServiceImpl implements IConsumerService {

    /**
     * 消息类型
     */
    private static final String MSG_TYPE  = "msgType";

    /**
     * 消息体
     */
    private static final String MSG_BODY = "msgBody";

    /**
     * A系统过来的消息
     */
    private static final String MSG_TYPE_A = "msgTypeA";
    
    @Override
    public boolean consumerHandler(Map<String, Object> message) {
        if(MSG_TYPE_A.equals(message.get(MSG_TYPE))){
            /// A系统消息处理逻辑
            
            return true;
            
        }
        return false;
    }
}

第二天哼着小曲走向工位时,leade拦住我说C系统也需要接进来,我心想,这不简单,不是留了一个msgType,给C系统增加个类型即可。代码修改:

public class ConsumerServiceImpl implements IConsumerService {

    /**
     * 消息类型
     */
    private static final String MSG_TYPE  = "msgType";

    /**
     * 消息体
     */
    private static final String MSG_BODY = "msgBody";

    /**
     * A系统过来的消息
     */
    private static final String MSG_TYPE_A = "msgTypeA";

    /**
     * C系统过来的消息
     */
    private static final String MSG_TYPE_C = "msgTypeC";
    
    @Override
    public boolean consumerHandler(Map<String, Object> message) {
        if(MSG_TYPE_A.equals(message.get(MSG_TYPE))){
            /// A 系统处理逻辑
            
            return true;
            
        } else if(MSG_TYPE_C.equals(message.get(MSG_TYPE))){
            /// C系统处理逻辑

            return true;

        }
        return false;
    }
}

第三天收到消息了,D系统也想加入。

回到工位,心想要不和C系统一样再加进去吧,反正留有类型字段msgType,来多少加多少。这样既简单有高效。

怎么办

一顿操作后,看着刚写完自己的代码,我陷入的沉思,心想要是后续F和E系统要加进来,继续这样加判断逻辑。然后会充斥着大量的if else的代码逻辑。

顿时觉得自己的代码不够优雅,那怎么办?作为有上进心的大好青年,觉得需要做出改变。

想到自己看到前几天看的策略模式,不就是可以替换大量的if else。很符合我们现在场景。

重构

先将可能需要的常量归到一个类里面去。

public interface MsgConstant {

    /**
     * 消息类型
     */
    String MSG_TYPE = "msgType";

    /**
     * 消息体
     */
    String MSG_BODY = "msgBody";

    /**
     * A系统过来的消息
     */
    String MSG_TYPE_A = "msgTypeA";

    /**
     * C系统过来的消息
     */
    String MSG_TYPE_C = "msgTypeC";

    /**
     * D系统过来的消息
     */
    String MSG_TYPE_D = "msgTypeD";
}

对不同系统过来的消息,其实都是在处理消息,但是因系统不同,底层的处理逻辑不同,可以创建一个处理消息的接口,根据系统来创建不同实现。

public interface IMessageExecute {

    /**
     * 消息具体执行
     * @param message
     * @return
     */
    boolean execute(Map<String, Object> message);

}

A系统消息:

@Service(MsgConstant.MSG_TYPE_A)
public class AMessageExecute implements IMessageExecute {

    @Override
    public boolean execute(Map<String, Object> message) {
        // A消息的处理逻辑
        return false;
    }
}

C系统消息:

@Service(MsgConstant.MSG_TYPE_C)
public class CMessageExecute implements IMessageExecute {

    @Override
    public boolean execute(Map<String, Object> message) {

        // C消息的处理逻辑
        return false;
    }
}

D系统消息:

@Service(MsgConstant.MSG_TYPE_D)
public class DMessageExecute implements IMessageExecute {

    @Override
    public boolean execute(Map<String, Object> message) {

        // D消息的处理逻辑
        return false;
    }
}

对于消息处理的server层,我们只需要根据消息类型,获取对应的消息处理实现类即可,并且这个动作也可做到动态实现。

@Service
public class ConsumerServiceImpl implements IConsumerService {

    @Autowired
    private Map<String,IMessageExecute> iMessageExecuteMap;

    @Override
    public boolean consumerHandler(Map<String, Object> message) {
        if (iMessageExecuteMap.containsKey(message.get(MsgConstant.MSG_TYPE))) {
            return iMessageExecuteMap.get(MsgConstant.MSG_TYPE).execute(message);
        }
        return false ;
    }
}

IMessageExecute的实现类会被全部注入到map中,只需从map中取出就可直接食用。

看着改造后的代码,心想后续E系统要加进来,只需为E系统去增加相关IMessageExecute的实现类,其他代码不用做任何修改,就可动态加入。

再一想,这不就是符合开闭原则,对扩展开放,对修改关闭。顿时觉得代码优雅了,摸鱼也跟自信了。

饭后思考

在适合的场景使用合适的设计模式,能让我们的代码更健壮,更简单化。在学完一种设计模式的时候,可以思考一下自己的业务代码适合这个场景,尝试去改造一下,也许就会发现新大陆。