You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何使用工厂类实例化接口?Spring 6示例相关技术疑问

关于《Pro Spring 6》中工厂类设计意义的疑问

我正在阅读《Pro Spring 6》一书,对书中的一个示例存在困惑。书中提到,更换MessageRenderer或MessageProvider接口的实现类需要修改代码,因此采用工厂类从配置文件读取实现类名称并完成实例化。但我有疑问:若为接口新增方法,实现类仍需修改,那么使用工厂类的意义究竟是什么?

相关代码

主类代码

public class HelloWorldDecoupledWithFactory {

    public static void main(String... args) {
        MessageRenderer mr = MessageSupportFactory.getInstance().getMessageRenderer()
                .orElseThrow(() -> new IllegalArgumentException("Service of type 'MessageRenderer' was not found!"));
        MessageProvider mp = MessageSupportFactory.getInstance().getMessageProvider()
                .orElseThrow(() -> new IllegalArgumentException("Service of type 'MessageProvider' was not found!"));
        mr.setMessageProvider(mp);
        mr.render();
    }
}

MessageSupportFactory类代码

public class MessageSupportFactory {

    private static MessageSupportFactory instance;
    private Properties props;
    private MessageRenderer renderer;
    private MessageProvider provider;

    private MessageSupportFactory() {
        props = new Properties();
        try {
            props.load(this.getClass().getResourceAsStream("/msf.properties"));
            String rendererClass = props.getProperty("renderer.class");
            String providerClass = props.getProperty("provider.class");
            renderer = (MessageRenderer) Class.forName(rendererClass).getDeclaredConstructor().newInstance();
            provider = (MessageProvider) Class.forName(providerClass).getDeclaredConstructor().newInstance();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    static {
        instance = new MessageSupportFactory();
    }

    public static MessageSupportFactory getInstance() {
        return instance;
    }

    public Optional<MessageRenderer> getMessageRenderer() {
        return renderer != null?  Optional.of(renderer) : Optional.empty();
    }

    public Optional<MessageProvider> getMessageProvider() {
        return provider!= null?  Optional.of(provider) : Optional.empty();
    }
}

解答

你搞混了工厂类解决的问题和接口版本变更的问题,这俩完全是两码事。

工厂类的核心作用是解耦接口的使用者和具体实现类:

  • 之前如果要换实现类,你得直接改主类里的new XXXRenderer()代码,重新编译部署;现在只需要改配置文件里的类名,不用碰业务代码,甚至不用重新编译,直接替换配置文件就行。这在很多场景下特别有用,比如你不想让业务代码依赖具体实现,或者需要在不同环境用不同实现的时候。

而接口新增方法需要修改实现类,这是接口契约变更带来的问题,不管你用不用工厂,只要接口变了,所有实现类都得跟着调整——这是面向接口编程的本质决定的,和工厂模式没关系。

简单说,工厂类管的是「怎么拿实现类」,不管「实现类该怎么写」。它解决的是替换实现的成本问题,不是接口变更的维护问题。

内容的提问来源于stack exchange,提问作者houhou

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 09:12:24