疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

优雅的代码--以多态为荣、写if...else为耻具体怎么操作?


 

 
  在和微信对接的过程中,微信的系统会发送很多不同类型的消息给我们的系统;并且我们在处理完成以后,也会返回各种不同的消息给微信。
        那么我们公众号的代码能否高效、合理处理这些信息呢?首先我们来说一下大多数拿到需求就写代码的人,写出来的代码处理流程:
public String process( String msg )
{
    // 获取消息类型
    String type = getType(msg);
    SendMessage send = null;
    if( "text".equals( type ) )
    {
        // 把msg转换为文本消息进行处理
        ReceiveTextMessage receive = unmarshalTextMessage( msg );
        send = processTextMessage( receive );
    }
    else if( "voice".equals( type ) )
    {
        // 把msg转换为语音消息进行处理
        ReceiveTextMessage receive = unmarshalVoiceMessage( msg );
        send = processVoiceMessage( receive );
    }
    // 如果有其他消息,在这里继续增加判断
    // 返回的消息可能也是有多种格式的
    String ret = "";
    if( send.getType().equals("image") )
    {
        ret = marshalImageMessage( send );
    }
    else if( send.getType().equals("text") )
    {
        ret = marshalTextMessage( send );
    }
    // 如果有其他消息,在这里继续增加判断
    return ret;
}
经常我们都说,要【以多态为荣、写if...else为耻】,那么我们到底该怎样实现不写if...else呢?且看下面的代码:
public String process( String msg )
{
    // 获取消息类型
    String type = getType(msg);
    // 获取接收消息转换器,并把msg转换为Java对象
    ReceiveMessageConverter receiveConverter = messageConverterFactory.getConverter( type );
    ReceiveMessage rm = receiveConverter.convert( msg );
    // 获取消息处理器,处理消息并得到结果消息
    MessageProcessor mp = messageProcessorFactory.getProcessor( rm.getClass() );
    SendMessage send = mp.process( rm );
    // 获取返回消息转换器
    SendMessageConverter sendConverter = messageConverterFactory.getConverter( send.getClass() );
    String ret = sendConverter.converter( send );
    return ret;
}
 
        我们可以看到后面一段代码,根本就没有if...else判断,代码显得非常优雅、精简、整洁;而且扩展性非常好:新增一种消息根本不需要修改这些代码,只需要在对应的工厂方法里面新增对应类型的转换器、处理器即可。
        所以一般写出来的工厂,里面的方法类似下面的代码:
// 定义一个成员变量来保存转换器和条件的关系
private static final Map<String, ReceiveMessageConverter> receiveConverterMap = new ConcurrentHashMap<>();
// 通过静态代码块初始化一个个的转换器
static
{
    receiveConverterMap.put("text", new ReceiveTextMessageConverter());
    receiveConverterMap.put("voice", new ReceiveVoiceMessageConverter());
         // 新增一个消息类型要处理,只需要在初始化的时候多put几个不同的转换器即可!
}
// 根据类型直接获取对应的转换器,根本不需要if...else
public ReceiveMessageConverter getConverter( String type )
{
    receiveConverterMap.get( type );
}
// 所有的其他转换器、处理器等都是一样的套路,不需要判断!
 
 
        事情到了这里,可以说我们已经实现了【以使用多态为荣、使用if...else为耻】,但是我们可以发现一个问题:如果我们不是接入微信,而是接入其他更复杂的消息接口,不是有限的几个消息类型,而是几十种、几百种各种不同的消息,我们的静态代码块就会显得特别臃肿、重复。
        虽然相当于使用if...else来讲,最后的这种代码依然没有判断、修改起来也非常直观,但是我们还是希望有更加简单的方法:能否增加一个jar文件,自动扫描jar文件里面的类,是否实现了我们需要的接口?如果扫描到以后,还会自动把实现类创建出来,并且添加到集合里面。这样就不需要一个个实现类来添加了,直接加入一个新的jar文件即可处理一种新的消息,代码会更加优雅、精简、整洁。
        这就必须要提到Java里面的SPI了,我们连new这种语句都可以去掉,欲知后事如何,且听下回分解!
 
 
【阅读原文】