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

工厂模式结合泛型时参数化类原始使用问题及优化咨询

泛型与工厂模式结合的实践问题及解决方案

背景

我学习了Factory模式和泛型的用法,正尝试将二者结合使用。以下是我的实践内容:

无泛型输入参数 - 无警告

public abstract class ArtifactCreator {
    public abstract void setArtifacts(String workflowInput);
}
public class FooArtifactCreator extends ArtifactCreator {
    @Override
    public void setArtifacts(String input) {
        return null;
    }
}
public class BarArtifactCreator extends ArtifactCreator {
    @Override
    public void setArtifacts(String input) {
        return null;
    }
}
public class Factory {
    public ArtifactCreator getArtifactCreator(String domain) {
        if (domain == "foo") {
            return new FooArtifactCreator();
        } else if (domain == "bar") {
            return new BarArtifactCreator();
        }
        return null;
    }
}

核心问题

上述代码中workflowInput被限定为String类型,但我希望它能支持通用POJO类型。

使用泛型后的警告问题

引入泛型后,我在Factory.java和Store.java中收到以下警告,希望通过正确使用泛型消除这些警告:

  • Raw use of parameterized class 'ArtifactCreator':出现在Store.java和Factory.java中
  • Unchecked call to 'setArtifacts(T)' as a member of raw type 'ArtifactCreator':出现在Store.java中

泛型版本的核心代码如下:

泛型版ArtifactCreator

public abstract class ArtifactCreator<T> {
    public abstract void setArtifacts(T workflowInput);
}

具体实现类

public class FooArtifactCreator extends ArtifactCreator<FooInput> {
    @Override
    public void setArtifacts(FooInput input) {
        return null;
    }
}
public class BarArtifactCreator extends ArtifactCreator<BarInput> {
    @Override
    public void setArtifacts(BarInput input) {
        return null;
    }
}

工厂类(未修正)

public class Factory {
    public ArtifactCreator getArtifactCreator(String domain) {
        if (domain == "foo") {
            return new FooArtifactCreator();
        } else if (domain == "bar") {
            return new BarArtifactCreator();
        }
        return null;
    }
}

输入类与Store类

public class Input {
    private String domain;
    private String otherInput;
    
    // getter方法省略
}
public class Store {
    private final Factory factory;
    
    public Store(Factory factory) {
        this.factory = factory;
    }

    public ArtifactCreator getCaseClosureArtifactFactory(Input req) {
        ArtifactCreator artifactCreator = factory.getArtifactCreator(req.getDomain());

        // 实际场景中 - 根据`Input` POJO中的`otherInput`字段创建FooInput或BarInput
        FooInput input = new FooInput();
        artifactCreator.setArtifacts(input);
        return artifactCreator;
    }
}

我想到的替代方案(存在缺陷)

我尝试过创建一个包含所有具体输入类型的WorkflowInput,但这种方法会存在多余的空字段,不够优雅:

public class WorkflowInput {
    private FooInput fooInput;
    private BarInput barInput;
    
    // getter/setter方法省略
}

public abstract class ArtifactCreator {
    public abstract void setArtifacts(WorkflowInput workflowInput);
}

public class FooArtifactCreator extends ArtifactCreator {
    @Override
    public void setArtifacts(WorkflowInput input) {
        FooInput fooInput = input.getFooInput(); // 提取特定输入
    }
}

public class BarArtifactCreator extends ArtifactCreator {
    @Override
    public void setArtifacts(WorkflowInput input) {
        BarInput barInput = input.getBarInput(); // 提取特定输入
    }
}

正确的泛型解决方案

以下是无需冗余字段、能消除所有警告的合理方案:

1. 修正泛型类与工厂类

首先确保ArtifactCreator是正确的泛型类,同时修改工厂类返回带通配符的泛型类型,避免原始类型:

public abstract class ArtifactCreator<T> {
    public abstract void setArtifacts(T workflowInput);
}

public class Factory {
    public ArtifactCreator<?> getArtifactCreator(String domain) {
        // 注意:字符串比较改用equals,避免引用比较问题
        if ("foo".equals(domain)) {
            return new FooArtifactCreator();
        } else if ("bar".equals(domain)) {
            return new BarArtifactCreator();
        }
        return null;
    }
}

2. 新增输入工厂类

创建一个输入工厂,根据Input生成对应的具体输入类型,保证类型与domain匹配:

public class InputFactory {
    public static Object createSpecificInput(Input req) {
        if ("foo".equals(req.getDomain())) {
            FooInput fooInput = new FooInput();
            // 根据req.otherInput初始化fooInput的字段
            return fooInput;
        } else if ("bar".equals(req.getDomain())) {
            BarInput barInput = new BarInput();
            // 根据req.otherInput初始化barInput的字段
            return barInput;
        }
        return null;
    }
}

3. 修正Store类,使用泛型捕获保证类型安全

通过泛型捕获方法,安全调用setArtifacts,消除unchecked警告:

public class Store {
    private final Factory factory;
    
    public Store(Factory factory) {
        this.factory = factory;
    }

    public ArtifactCreator<?> getCaseClosureArtifactFactory(Input req) {
        ArtifactCreator<?> artifactCreator = factory.getArtifactCreator(req.getDomain());
        Object specificInput = InputFactory.createSpecificInput(req);
        
        // 安全调用setArtifacts
        setArtifactsSafely(artifactCreator, specificInput);
        return artifactCreator;
    }

    @SuppressWarnings("unchecked")
    private <T> void setArtifactsSafely(ArtifactCreator<T> creator, T input) {
        creator.setArtifacts(input);
    }
}

方案说明

  • 该方案通过泛型捕获机制,确保ArtifactCreator和输入类型的匹配性,因为InputFactory与Factory使用同一个domain生成对应实例,类型一致性有保障,因此@SuppressWarnings("unchecked")的使用是安全的。
  • 无需创建包含所有输入类型的冗余类,保持代码的简洁性和扩展性,新增输入类型时只需扩展InputFactory和对应的ArtifactCreator实现即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 00:01:09