Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/397.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java SpringBoot中的抽象工厂模式@Service_Java_Spring Boot - Fatal编程技术网

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