如何在编译时生成Java工厂?

时间:2015-09-21 10:07:05

标签: java reflection

我有一个已经实现了50次的界面,我的应用程序将继续随着新的实现而发展。应根据其名称(这是每个实现中可用的常量)加载这些实现。

我想避免在运行时使用反射(因为reflections lib会拉动3Mb的依赖项,我需要保持我的jar尽可能小)并且我还想避免向我添加一个条目每次添加实施时都会出厂。

所以我想知道:如何在编译时自动执行此操作?我基本上只需要构建一个Implmentation.NAME => ImplmentationConstructor

的地图

由于

编辑:我真正想要的是不必关心编写代码来加载这些类。这可能意味着工厂自动生成编译(完整代码生成)或使用某种类似ServiceLoader的工具,该工具支持自动生成所需文件和支持带参数的构造函数。现在我能想到的最简单的解决方案是在我的单元测试中使用反射来检查所有实现是否可以通过我的构造函数访问,如果没有,则在控制台中输出需要放入我工厂的代码,以便它们是

2 个答案:

答案 0 :(得分:3)

Java ServiceLoader可用于管理(和选择)大量接口实现。您添加一个以接口命名的文件,其中包含所有实现的完全限定名称: -

 META-INF/services/com.my.interface.MyInterface

ServiceLoader可以为您加载和管理所有实现。在工厂方法中,您可以选择最合适的实现并将其返回。

 ServiceLoader<MyInterface> impls  = ServiceLoader.load(MyInterface.class);

for(MyInterface impl : impls) {
     //iterating over each impl
 }

答案 1 :(得分:0)

使用enum s可以轻松灵活地完成经典工厂模式。

// What my factory can make.
interface Stuff {

}

// Some concrete implementations of Stuff.
private static class RollsRoyce implements Stuff {

    public RollsRoyce() {
    }
}

private static class Boeing implements Stuff {

    public Boeing() {
    }
}

// Each element in the factory must be able to make Stuff.
interface MakesStuff {

    Stuff makeOne();
}

enum Factory implements MakesStuff {

    Car {

                @Override
                public Stuff makeOne() {
                    return new RollsRoyce();
                }

            },
    Plane {
                @Override
                public Stuff makeOne() {
                    return new Boeing();
                }

            };

    // Special for making from a String name.
    public static Stuff make(String type) {
        // Will throw an exception if the name is not recognised.
        return Factory.valueOf(type).makeOne();
    }
}