Java 构造函数自动连接到不同参数的实现的设计模式

Java 构造函数自动连接到不同参数的实现的设计模式,java,spring,spring-mvc,spring-boot,Java,Spring,Spring Mvc,Spring Boot,我有一个带有两个实现的接口,现在我必须添加更多的实现。每个实现接口在构造函数中都有不同的参数,这些参数会自动连接,bean也会被注入。 我需要编写一个公共工厂方法,如果我传入一个客户机,它将返回特定类型的实现,并设置所有自动连接属性。请告诉我怎么做 Interface Example{ List<String> getData(String url); boolean isCorrectData(String var1, String var2); } 客户2: public cl

我有一个带有两个实现的接口,现在我必须添加更多的实现。每个实现接口在构造函数中都有不同的参数,这些参数会自动连接,bean也会被注入。 我需要编写一个公共工厂方法,如果我传入一个客户机,它将返回特定类型的实现,并设置所有自动连接属性。请告诉我怎么做

Interface Example{
List<String> getData(String url);
boolean isCorrectData(String var1, String var2);
}
客户2:

public class client2 implements Example{
final YclientConfig config;
final RestTemplate template;

@Autowired
public client2(YClientConfig config, @Qualifier(“template2”)  RestTemplate template){
this.config = config;
this.template = template;
}
现在,我正在尝试编写一个工厂类,其中我传入了客户机名称(客户机1或客户机2),工厂将返回一个完整构造的示例实例,因此不应该存在任何未实现的依赖项。 我需要通过工厂方法注入所有依赖项。 您能提供建议吗。

一般说明 您应该尝试在
工厂中使用反射。可以通过创建键值对的属性文件(只是一个名为
properties.config
的基本文本文件)来设置反射。这允许您更改文本文件中的实现。文本中此格式的示例如下:

ClientConfiguration,Client1
其中,
ClientConfiguration
是访问客户机配置的特定键,您猜对了。返回的值是字符串形式的“Client1”。如果要使用
Client2
,只需更改该值即可

在属性文件上使用反射 下一步是使用反射将此字符串更改为实际的
Client1
类型。您不能直接转换到
Client1
,而是要转换到客户端配置,因为客户端配置将是所有实现的父类型。为此,需要一个properties对象。然后,您需要一个输入流对象来读取properties.config文件,并将该文件中的属性添加到新创建的properties对象中。不这样做将意味着您的属性对象将是空的,因此对您没有帮助

Properties prop = new Properties()
InputStream input = new FileInputstream(//put your properties.config filename here)
prop.load(input)
Clientconfig clientconfig = prop.get(//input the key of the implementation you want here)
//对于本例,键应为
ClientConfiguration
,并确保字符串与文件中的匹配

使用反射类类型创建具有正确格式数据的对象实例 现在您可以获得类类型了,您可以调用构造函数并基于数据设置参数。我不知道数据的具体格式,但我建议使用CommaseOperatedValue-like格式,其中文件包含
Client1
Client2
“数据”的一些描述。那么您应该让这个描述的第一行是类的字段。例:

//inside Foo.txt

config,template
config_a,template_a
config_b,template_b
...
使用数据和类类型创建任何类类型的实例,而不考虑字段的数量 通过这种方式格式化数据,您可以构造这些
客户机
对象,而无需像通常那样在工厂类中调用它们的构造函数
Client1 Client1=new Client1(arg1,arg2)
。相反,您可以制作一个
字段映射
(字段名称映射为
字符串
字段
对象)

//读取文件并将其放入字符串数组或类似的数组中
Map fieldmap=新的Hashmap
Constructor=clientconfig.getConstructor
ClientConfig objectinstance=constructor.inkvoke(//在此处用null填充每个参数)
//将所有对放在fieldmap中
用于(字符串)fieldname://insert 文件的第一行(此处){
fieldmap.put(字段名、字段)
}
//对于对象中的每个字段,从feildmap中检索feild值并进行设置
//在对象中使用匹配的名称
for(字段:objectinstance){
set(objectinstance,fieldmap.get(field.getName))
}

现在您有了一个完全构造的类实例!如果要更改实现,只需更改
properties.config
,剩下的工作将由
工厂来完成。当实际创建这些类的实例时,大多数代码都属于
工厂
,每个构造都是相同的。唯一改变的是反映在中的类,但是假设您的数据采用正确的格式(如上所述),您应该能够构造您想要的任何类型的实例。您甚至可以更进一步,将其转换为通用对象工厂,因为这基本上就是构造任何类实例的东西。请注意,我不保证复制粘贴,但我通常是这样做的。

您能更具体地说明您的具体用例吗?通常有更干净的方法来做到这一点。例如,您真的需要多个
restemplate
选项吗?如果是这样的话,是什么让它们不同呢?我需要创建一个工厂类,它根据我传递的客户机字符串返回特定类型的客户机,这个字符串没有进一步解释。
//inside Foo.txt

config,template
config_a,template_a
config_b,template_b
...
//get your file read and into an array of strings or something similar
Map<String,Field> fieldmap = new Hashmap
Constructor constructor = clientconfig.getConstructor
ClientConfig objectinstance = constructor.inkvoke(//fill in every argument with null here)
//put all the pairs in the fieldmap
for(String fieldname://insert first line of file here){
fieldmap.put(fieldname,Field)
}

//for each field in the object, retrieve the feild value from the feildmap and set it 
//in the object using the matching name
for(Field field:objectinstance){
    field.set(objectinstance,fieldmap.get(field.getName))
}