I am designing a system where two modules, one which gestions files and another users. For certain logic operations, they need the services offered by each other.
Each module is represented by a singleton which implements a interface offering some services to each other, with abstract factories to provide them, like so:
public class UserMain implements UserInternalService {
/*
* Internal interfaces
*/
/**
* Allows interaction with the projects database.
*/
FilesInternaService fileSystem;
/**
* Constructor is private, as this is a singleton.
*/
protected UserMain() {
}
private static UserMain singleton = null;
/**
* Singleton factory. Returns a reference to the singleton. If there is no
* reference yet, creates it.
*/
protected static synchronized UserMain getReference() {
if (singleton == null) {
singleton = new UserMain();
singleton.fileSystem = FileMain.getInternalService();
}
return singleton;
}
/**
* Factory method for the singleton as a UserInternalService
*/
public static UserInternalService getUserInternalService() {
return getReference();
}
}
And the file module main class is like so:
public class FileMain implements FilesInternaService{
/**
* Interface to user subsystem for request validation, etc.
*/
UserInternalService userSystem;
/**
* Creation of instances aside from singleton disallowed.
*/
protected FileMain(){};
private static FileMain singleton = null;
/**
* Singleton factory.
* Returns a reference to the singleton.
* If there is no reference yet, creates it.
*/
protected synchronized static FileMain getReference(){
if(singleton == null)
singleton = new FileMain();
singleton.userSystem = UserMain.getUserInternalService();
return singleton;
}
/**
* Abstract factory for Internal Services singleton.
* @return
*/
public static FilesInternaService getInternalService(){
return getReference();
}
}
I am not enterely sure that I am correctly handling the circular dependency. Is there any way this may break unexpectedly?
EDIT: As it has been answered below, the correct way to handle this is injection. However, the correct way to handle this is not what I am asking here, but rather how could this specific solution blow up.
The clean way to handle this is using dependency injection, to keep the dependencies at the interface level.
It's ok for UserMain
to depend on FilesInternaService
and it's ok for FileMain
to depend on UserInternalService
; but it's not ok for UserMain
to depend on FileMain
or for FileMain
to depend on UserMain
. In other words, it's not ok to depend on concrete implementation.
An instance of FilesInternaService
should be injected into UserMain
and an instance of UserInternalService
should be injected into FileMain
.
References
来源:https://stackoverflow.com/questions/37444940/spot-problems-with-circular-dependency