Java interfaces, the creator patterns and the “getInstance()” method or equivalent
首先我想说的是,我的问题源于Java中的接口不允许使用静态方法。关于这件事的原因(例如这里)已经有过讨论。所以我们不要再谈这个了。我正在寻找一种方法,让我的接口创建一个自己的实例(而不是它的实现)并返回它。尽管我一直在玩单件模式、工厂模式和抽象工厂模式,但我仍然无法实现我的目标。
要详细说明我在尝试什么-这是我的界面:
1 2 3 4 5 6 7 | public interface NoteDataStore { public boolean deleteNote(long noteId); public boolean addNote(Note note); public List<Note> listNotes(); public boolean editNote(long noteId, Note note); public List<Note> search(String searchString); } |
下面是我的业务逻辑层:
1 2 3 4 5 6 7 8 9 10 | public class BusinessLogicLayer { public BusinessLogicLayer(){ /* * GOAL: To get an instance of NoteDataStore here, * without being aware of the implementation class. */ } } |
我尝试使用这样的工厂模式:
1 2 3 4 5 6 7 8 9 10 11 12 13 | public interface NoteDataStoreFactory { public NoteDataStore getDataStoreInstance(); } public class NoteDataStoreFactoryImpl implements NoteDataStoreFactory{ public NoteDataStore getDataStoreInstance(){ return NoteDataStoreImpl.getInstance(); /* * Here, NoteDataStoreImpl is an implementation of NoteDataStore. * This should be transparent to my business logic layer. */ } } |
但是,这仍然需要业务逻辑层了解实现类
1 | NoteDataStore = new NoteDataStoreFactoryImpl().getDataStoreInstance(); |
我该怎么解决这个问题?关于要使用的具体实现类,我如何让BusinessLogicClayer处于黑暗之中?
编辑:更详细的问题背景一些答案建议使用Spring这样的框架。唉,我不能这样做,因为这个应用程序针对各种移动平台(Android、BlackBerry、Javame)。我本应该在我最初的问题中澄清这一点——抱歉没有这样做。
我的主要目的是跨平台开发一个应用程序。用户界面、数据库访问、HTTP传输层等必须专门为每个平台进行编码。然而,业务逻辑非常简单,足以保证跨所有平台的公共层。我打算将业务逻辑层作为JAR库分发。同样,解析和框架层(对于JSON/XML)。
在So(关于我是否应该走这条路)已经有了一个关于这个的讨论——逻辑代码重用。但是,假设这是可以的,并且我继续使用分层方法,并且希望在代码中有一个公共层。现在,我的处境是这样的:
请注意,如果我使用工厂模式或其他类似模式,我可以负担得起每个平台特定的层。因此,工厂方法/类本身可以了解
各层的典型用途如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | public class NoteDataStoreAndroid implements NoteDataStore{ public boolean deleteNote(long noteId){ /* * Android-specific database code */ } /* ... similarly, other methods */ } public class AndroidCoreApp{ public void doBusinessLogic(){ BusinessLogicLayer businessLogic = new BusinessLogicLayer(); businessLogic.startBusinessLogic(); } } |
有关于如何处理这个场景的输入吗?
您的类应该从外部接受工厂实例。当你自己创建实例的时候——你什么都没有实现,你在这里是正确的。
这里有几种技术。一般来说,它们属于一种非常普遍的东西,简称为控制反转或IOC。此外,了解"控制容器倒置"或IOCC也很有用。例如,Java有Spring。你应该问真正的Java家伙关于其他人:
还可以看看这篇文章。
如果您想返回一个实现,可以使用一个匿名的内部类来实现。
1 2 3 | NoteDataStore myImplementation = new NoteDataStore (){ //Implement methods here }; |
建议您使用ID框架,比如Guice和其他框架。不仅仅是使用工厂模式。
我最终接受了@ray tayek在对原始问题的评论中提出的建议。我只是在创建
这个简单的解决方案非常适合我的需要,因为我不需要工厂。我的主要目标是让BL层不知道它使用的接口的确切实现类。现在,它不是工厂,而是核心的"控制器"层,它创建接口的具体实现,并将它们提供给BL层。这太完美了!
这是代码段。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | public class NoteDataStoreAndroid implements NoteDataStore{ public boolean deleteNote(long noteId){ /* * Android-specific database code */ } /* ... similarly, other methods */ } public class AndroidCoreApp{ public void doBusinessLogic(){ BusinessLogicLayer businessLogic = new BusinessLogicLayer(new NoteDataStoreAndroid()); businessLogic.startBusinessLogic(); } } public class BusinessLogicLayer { private NoteDataStore mDataStore; public BusinessLogicLayer(NoteDataStore dataStore){ this.mDataStore = dataStore; //Do something useful with mDataStore } public void startBusinessLogic(){ //Do something useful with mDataStore } } |
您看过类似guice和spring的IOC/Dependency注入框架吗?他们可能太重了,无法满足你的需求,但他们肯定能解决你所描述的问题。它们允许根据接口编写所有业务层代码,并通过IOC框架定义实际实现。我个人是Spring的忠实粉丝,在过去6年中几乎每一个Java应用程序中都使用过它。