背景

org.springframework.beans及org.springframework.context这两个包是Spring IoC容器的基础,
其中重要的类有BeanFactory,BeanFactory是IoC容器的核心接口,其职责包括:实例化、定位、配置应用程序中的
对象及建立这些对象间的依赖关系。

ApplicationContext作为BeanFactory的子类,在Bean管理的功能上得到了很大的增强,也更易于与Spring AOP集成使用。
今天我们要讨论的并不是BeanFactory或者ApplicationContext的实现原理,而是对ApplicationContext的一种实际应用方式。

应用

在实际工作中,我们经常会遇到一个接口及多个实现类的情况,并且在不同的条件下会使用不同的实现类。

需求

"假设从A点到B点有多种交通方式,每种交通方式的费用不同,可以根据乘客的需要进行选择"

实现

我们的设计如下:有一个交通方式的接口,接口有两个方式,一个查询费用、一个查询该交通方式的类型,同时,我们可以用一个枚举类型类标识交通类型。

我们还需要一个工厂类来根据交通类型标识查找该交通类型的Bean实例,从而使用该实例,获得交通类型的详细信息及该交通类型的操作。

代码如下:

接口:

/**
 * 交通方式
 */
public interface TrafficMode {
 
    /**
     * 查询交通方式编码
     * @return 编码
     */
    TrafficCode getCode();
 
    /**
     * 查询交通方式的费用,单位:分
     * @return 费用
     */
    Integer getFee();
 
}

枚举:

/**
 * 交通类型枚举
 */
public enum TrafficCode {
 
    TRAIN,
    BUS
 
}

接口有两个实现类:

/**
 * 汽车方式
 */
@Component
public class BusMode implements TrafficMode {
 
    @Override
    public TrafficCode getCode() {
        return TrafficCode.BUS;
    }
 
    @Override
    public Integer getFee() {
        return 10000;
    }
 
}
/**
 * 火车方式
 */
@Component
public class TrainMode implements TrafficMode {
 
    @Override
    public TrafficCode getCode() {
        return TrafficCode.TRAIN;
    }
 
    @Override
    public Integer getFee() {
        return 9000;
    }
 
}

工厂类:

/**
 * 交通方式工厂类
 */
@Component
public class TrafficModeFactory implements ApplicationContextAware {
 
    private static Map<TrafficCode, TrafficMode> trafficBeanMap;
 
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Map<String, TrafficMode> map = applicationContext.getBeansOfType(TrafficMode.class);
        trafficBeanMap = new HashMap<>();
        map.forEach((key, value) -> trafficBeanMap.put(value.getCode(), value));
    }
 
    public static <T extends TrafficMode> T getTrafficMode(TrafficCode code) {
        return (T)trafficBeanMap.get(code);
    }
 
}

验证

有了上面的代码之后,我们一起通过单元测试来看一下效果,单元测试代码片段如下:

    @Test
    public void testGetTrafficMode() {
        TrafficMode mode = TrafficModeFactory.getTrafficMode(TrafficCode.BUS);
        Assert.assertEquals(mode.getFee().intValue(), 10000);
 
        mode = TrafficModeFactory.getTrafficMode(TrafficCode.TRAIN);
        Assert.assertEquals(mode.getFee().intValue(), 9000);
    }

运行之后的结果呢?必然是通过。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐