更好地设计构造函数中的初始化

时间:2014-07-24 21:22:09

标签: java oop

我有一个看起来像这样的类,它根据从凭证服务检索的凭据充当客户端的工厂。它构建客户端一次,并在每次调用时返回。

public class ClientFactory {
   private CredentialService credentialService;
   private ClientA clientA; 

   public ClientFactory(CredentialService credentialService){
      this.credentialService = credentialService;
      //initialization in constructor
      this.clientA = buildClientA(credentialService.getCredentials());
   }

   public ClientA getClientA(){
       return clientA;
   }

   /** Build new ClientA using crendentials*/
   private ClientA buildClientA(String credentials){
     return new ClientA(credentials);
   } 
}

我看到的问题是构造函数中的第2行,它基本上开始使用依赖关系' credentialService'立即初始化其他依赖项。如果其他开发人员在构造函数中移动代码的顺序,它将开始失败。其他选项也是改变方法getClientA()

   public ClientA getClientA(){
      if(clientA == null) {
        this.clientA = buildClientA(credentialService.getCredentials());
      }
       return clientA;
   }

但它有线程安全问题。有没有更好的方法来设计上面的课程,这避免了我上面强调的问题?

由于

3 个答案:

答案 0 :(得分:3)

好吧,

this.clientA = buildClientA(credentialService.getCredentials());依赖于传递给构造函数的参数credentialService,而不是成员this.credentialService。因此,初始化的顺序并不重要。

顺便说一句,为了安全起见并避免混淆,我不会对构造函数和成员的参数使用相同的名称。

答案 1 :(得分:1)

只是不要将对CredentialService的引用保存为实例变量,并继续将credentialService.getCredentials()传递给bulldClientA。您尚未使用实例变量credentialService

答案 2 :(得分:1)

你所谓的ClientFactory看起来只是ClientA。那么,如果您想避免创建额外的ClientA个对象,为什么不让工厂依赖凭据并共享对ClientA的引用呢?

public class ClientFactory {
   private final CredentialService credentialService;

   public ClientFactory(CredentialService credentialService){
      this.credentialService = credentialService;
   }

   public ClientA newClientA(String credentials){
     return new ClientA(credentials);
   } 
}

如果您想拥有潜在客户群,则可以共享Supplier<ClientA>

Supplier<ClientA> simpleSupplier = Suppliers.ofInstance(ClientFactory.newClientA()); // guava
Supplier<ClientA> allNewSupplier = () -> ClientFactory.newClientA(); // java 8 lambda
ClientA cachedClient = simpleSupplier.get();
ClientA newClient = allNewSupplier.get();