【问题标题】:Design pattern for Implementations with constructors autowired to different arguments具有自动装配到不同参数的构造函数的实现的设计模式
【发布时间】:2018-07-13 02:38:49
【问题描述】:

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

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

客户端1:

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 实例,因此不应该有任何未实现的依赖项。 我需要通过工厂方法注入所有依赖项。 能给个建议吗?

【问题讨论】:

  • 您能否更具体地了解您的具体用例? 通常有更简洁的方法可以做到这一点。例如,您真的需要多个RestTemplate 选项吗?如果是这样,它们有何不同?
  • 我需要创建一个工厂类,它根据我传递的客户端字符串返回特定类型的客户端
  • 这没有进一步解释。

标签: java spring spring-mvc spring-boot


【解决方案1】:

一般说明

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

ClientConfiguration,Client1

ClientConfiguration 是访问的特定密钥,您猜对了,您的客户端配置。并且返回的值为“Client1”作为字符串。如果您想使用Client2,只需更改值即可。

在属性文件上使用反射

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

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,并确保字符串匹配一个 //on file

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

现在您可以获得类类型,您可以调用构造函数并根据数据设置参数。我不知道数据的具体格式,但我建议使用类似 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.configFactory 将完成剩下的工作。大多数代码在实际创建这些类的实例时属于Factory,并且每个构造都是相同的。唯一改变的是反映了什么类,但假设您的数据格式正确(如上所述),您应该能够构造您想要的任何类型的实例。你甚至可以更进一步,把它变成一个通用对象工厂,因为它基本上就是这样,它可以构造任何类的实例。请注意,我对复制粘贴不做任何保证,但我通常是这样做的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-09
    • 2014-04-18
    • 1970-01-01
    • 2012-05-06
    • 1970-01-01
    • 2020-05-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多