Reputation: 6998
I have a class that looks something like this which acts as factory for clients based on credentials retrieved from credentials service. It builds clients one time and returns that on every call.
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);
}
}
Issue that I see with this is line 2 in the constructor which basically start using dependency 'credentialService' to initialize other dependencies immediately. If some other developer moves around order of code in constructor, it will start failing. Other option is too change method getClientA()
to this.
public ClientA getClientA(){
if(clientA == null) {
this.clientA = buildClientA(credentialService.getCredentials());
}
return clientA;
}
But it has thread safety issues. Is there a better way to design above class which avoids concerns I highlighted above?
Thanks
Upvotes: 3
Views: 106
Reputation: 23643
What you call ClientFactory
looks like it's really just a ClientA
. So why not have a factory that depends on the credentials and share a reference to a ClientA
if you want to avoid creating extra ClientA
objects?
public class ClientFactory {
private final CredentialService credentialService;
public ClientFactory(CredentialService credentialService){
this.credentialService = credentialService;
}
public ClientA newClientA(String credentials){
return new ClientA(credentials);
}
}
If you want to have a pool of clients potentially, you can share a Supplier<ClientA>
instead.
Supplier<ClientA> simpleSupplier = Suppliers.ofInstance(ClientFactory.newClientA()); // guava
Supplier<ClientA> allNewSupplier = () -> ClientFactory.newClientA(); // java 8 lambda
ClientA cachedClient = simpleSupplier.get();
ClientA newClient = allNewSupplier.get();
Upvotes: 1
Reputation: 394146
Well,
this.clientA = buildClientA(credentialService.getCredentials());
relies on the parameter credentialService
passed to the constructor, not on the member this.credentialService
. Therefore, the order of the initializations doesn't matter.
BTW, just to be safe and avoid confustion, I wouldn't use the same name for the parameter of the constructor and the member.
Upvotes: 3
Reputation: 5496
Just don't save off a reference to theCredentialService
as an instance variable, and continue passing credentialService.getCredentials()
to bulldClientA
. You are already not using the instance variable credentialService
.
Upvotes: 1