Java SpringBoot中的抽象工厂模式@Service
我想知道如何在我的应用程序中使用抽象工厂实现类作为@服务。 我有几个想要的逻辑提供者,并通过构造函数注入它们。问题是我不确定我的工厂是否应该有建造师,如果应该,是否应该是私人的 我已经将这个类注释为@服务,但我想知道这些是否都是好的,最佳实践是什么。 谢谢你,如果上面乱七八糟的话,很抱歉,这实际上是我的第一个问题和帖子 以下是我的代码片段:Java SpringBoot中的抽象工厂模式@Service,java,spring-boot,Java,Spring Boot,我想知道如何在我的应用程序中使用抽象工厂实现类作为@服务。 我有几个想要的逻辑提供者,并通过构造函数注入它们。问题是我不确定我的工厂是否应该有建造师,如果应该,是否应该是私人的 我已经将这个类注释为@服务,但我想知道这些是否都是好的,最佳实践是什么。 谢谢你,如果上面乱七八糟的话,很抱歉,这实际上是我的第一个问题和帖子 以下是我的代码片段: private final FirstClient first; 私人决赛第二名; private FactoryImpl(第一个客户端第一,第二个客户端第
private final FirstClient first;
私人决赛第二名;
private FactoryImpl(第一个客户端第一,第二个客户端第二){
this.first=first;
这个秒=秒;
}
@凌驾
公共客户端获取(字符串clientName){
if(“First”.equalsIgnoreCase(clientName)){
先把这个还给我;
}else if(“Second”.equalsIgnoreCase(clientName)){
把这个还给我;
}
抛出新的UnknownClientException(“服务不支持客户端:+clientName”);
}
既然您说这个类被注释为@Service
,我假设您希望两个客户端都自动连接到它,并且它们都是bean
在这种情况下,您可以在构造函数中自动关联它们(在这种情况下,构造函数应该是公共的)。或者,您可以不使用构造函数,直接(或通过setter方法)自动关联字段-这不太推荐,更好的做法是使用构造函数自动关联。事实上,Spring框架的核心是一种超级灵活和强大的抽象工厂。如果您使用的是Spring,那么您应该将所有的类创建功能委托给SpringCore。在您的情况下,我更喜欢使用SpringJava
配置来创建类。相当于你们工厂在春天的样子
@配置
公共类ServiceConfig{
@豆子
公共关系客户机firstClient(){
返回新的FirstClient();
}
@豆子
公众情绪客户机secondClient(){
返回新的SecondClient();
}
}
在SpringCore识别出这个类之后,每当其他SpringBean需要它时,它就会将它作为一个工厂来获取服务实例。您不需要像在工厂中那样调用任何类型的get
方法。Spring是自动完成的
@服务
公共类服务{
私人最终客户第一客户;
@自动连线
私有SomeService(客户端第一客户端){
this.firstClient=firstClient;
}
//这里有一些商业逻辑
}
值得一提的是,Spring配置中工厂方法的名称是由该方法创建的bean(服务)的名称,该名称和类类型用于查找自动连接所需的bean>P>你应该考虑以下实践来应用最佳实践:
不要将对象字段紧密耦合,而是注入它们。这将允许在需要时更改对象字段类
为了实现第1点,始终按照合同工作,即使用接口
每次调用factory时,确定是需要单例对象还是新对象
抽象工厂的可维护性
就你而言,你已经遵守了第2条。休息一下,
a) 为FirstClient
和SecondClient
创建bean
b) 如果这些必须是从final关键字看得很明显的单例,但工厂类看不到,则将这两个客户机类都设置为单例
c) 不要使用字符串clientName,而是创建一个枚举,因为它更易于维护和安全,因为您总是查找定义良好的值
d) 不要使用if-else,而是使用作为工厂后期构建填充的地图。这将加快获取豆子的速度
e) 您还可以考虑延迟初始化:)
class-factoryImpl{
私有地图工厂地图;
@自动连线
私人最终客户优先;
@自动连线
私人决赛第二名;
@凌驾
公共客户端获取(字符串clientName){
Client.getByName(clientName);
如果(!factoryMap.contains(客户端)){
抛出新的UnknownClientException(“服务不支持客户端:”
+客户名称);
}
返回factoryMap.get(Clients.getByName(clientName));
}
我知道你已经接受了答案,但我只想提供我自己的意见。首先,我认为你不想使用抽象工厂模式,似乎你不是在创建对象,只是想根据它们的名称定位客户端对象。这是Locator的工作,我们称之为ClientLocator(因为没有更好的名字)
我们的想法是创建一个名为ClientLocator
的类,该类实现ApplicationContextAware
。通过实现这个接口,Spring将通过setter方法注入一个ApplicationContext
对象。使用ApplicationContext
对象,我们可以根据bean的名称查找bean,然后我们可以检查k bean的类型以确保得到正确的bean,如果没有得到,则抛出错误
下面是代码的外观
客户
//mountainclient.java
公共接口客户端{
无效调用();
}
//FirstClient.java
@服务
公共类FirstClient实现了一个客户端{
@凌驾
公开作废通知(){
System.out.println(“来自第一个客户端的你好”);
}
}
//SecondClient.java
@服务
公共类SecondClient实现了一个客户端{
@凌驾
公开作废通知(){
System.out.println(“来自第二个客户端的你好”);
}
}
ClientLocator.java
@组成部分
公众的
class SentimentFactoryImpl{
private Map<Client, SentimentClient> factoryMap;
@Autowired
private final FirstClient first;
@Autowired
private final SecondClient second;
@Override
public SentimentClient get(String clientName) {
Client Client.getByName(clientName);
if(!factoryMap.contains(client)){
throw new UnknownClientException("Service doesn't provide support for client: "
+ clientName);
}
return factoryMap.get(Clients.getByName(clientName));
}