问题描述
我正在设计一个系统,其中两个模块,一个妊娠文件和另一个用户.对于某些逻辑操作,他们需要彼此提供的服务.
每个模块由一个单身人士表示,该单元实现了一个界面,可提供一些服务,并提供抽象工厂提供它们,例如:
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(); } }
和文件模块主类就像:
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(); } }
我不确定自己是否正确处理圆形依赖性. 有什么办法可能意外地破裂?
编辑:正如下面已经回答的那样,处理此操作的正确方法是注射.但是,处理此问题的正确方法不是我在这里问的,而是该特定解决方案如何爆炸.
推荐答案
处理此操作的干净方法是使用依赖注入,以使依赖关系保持在接口级别.
UserMain可以依赖FilesInternaService,FileMain依赖UserInternalService是可以的.但是,UserMain依赖FileMain或FileMain依赖UserMain是不对的.换句话说,依赖具体的实现是不行的.
应将FilesInternaService的实例注入UserMain,并应将UserInternalService的实例注入UserInternalService.
参考
问题描述
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