具有自动构造到不同参数的构造函数的实现的设计模式

时间:2018-07-13 02:38:50

标签: java spring spring-mvc spring-boot

我有一个带有两个实现的接口,现在我必须添加更多的实现,每个实现接口在构造函数中都有不同的参数,它们会自动连接并且正在注入Bean。 我需要编写一个通用的工厂方法,如果我传入一个客户端,并且该方法返回设置了所有自动连线属性的特定实现类型。请告知该怎么办?

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

Client1:

public class client1 implements Example{
final XclientConfig config;
final RestTemplate template;

@Autowired
public client1(XClientConfig config, @Qualifier(“template1”)  RestTemplate template){
this.config = config;
this.template = template;
}

客户端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),工厂将返回Example的完整实例,因此不应存在任何未实现的依赖项。 我需要通过工厂方法注入所有依赖项。 你能建议吗?

1 个答案:

答案 0 :(得分:0)

概述

您应该尝试在Factory中使用反射。可以通过创建键值对的属性文件(只是名称为properties.config的基本文本文件)来建立反射。这使您可以更改文本文件中的实现。这种格式的文字示例如下:

ClientConfiguration,Client1

其中ClientConfiguration是访问的特定密钥,您猜对了,这是您的客户端配置。返回的值为String的“ Client1”。如果要使用Client2,只需更改值即可。

在属性文件上使用反射

下一步是使用反射将字符串更改为实际的Client1类型。您不能直接转换为Client1,而是要转换为“客户端配置”,因为这将是所有实现的父类型。为此,您需要一个属性对象。然后,您需要一个Input流对象来读取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,并确保字符串与文件上的//字符串匹配

使用Reflected Class类型创建具有正确格式数据的对象实例

现在,您可以获取类类型,您可以调用构造函数并根据数据设置参数。我不知道数据的具体格式,但我建议使用CommaSeperatedValue之类的格式,其中文件包含通过Client1Client2“数据”进行的描述。然后,您应该使该轮廓的第一行是该类的字段。例如:

//inside Foo.txt

config,template
config_a,template_a
config_b,template_b
...

使用数据和类类型创建任何类类型的实例,而与字段数无关

通过这种方式格式化数据,您可以构造这些Client对象,而无需像通常使用Client1 client1 = new Client1(arg1,arg2)那样在Factory类中调用它们的构造函数。相反,您可以制作一个Fieldmap(字段名称从StringsFeild对象的映射)

//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))
}

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