Java接口,创建者模式和“getInstance()”方法或等效方法

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.
         */

    }
}

但是,这仍然需要业务逻辑层了解实现类NoteDataStoreFactoryImpl,因此:

1
NoteDataStore = new NoteDataStoreFactoryImpl().getDataStoreInstance();

我该怎么解决这个问题?关于要使用的具体实现类,我如何让BusinessLogicClayer处于黑暗之中?

编辑:更详细的问题背景

一些答案建议使用Spring这样的框架。唉,我不能这样做,因为这个应用程序针对各种移动平台(Android、BlackBerry、Javame)。我本应该在我最初的问题中澄清这一点——抱歉没有这样做。

我的主要目的是跨平台开发一个应用程序。用户界面、数据库访问、HTTP传输层等必须专门为每个平台进行编码。然而,业务逻辑非常简单,足以保证跨所有平台的公共层。我打算将业务逻辑层作为JAR库分发。同样,解析和框架层(对于JSON/XML)。

在So(关于我是否应该走这条路)已经有了一个关于这个的讨论——逻辑代码重用。但是,假设这是可以的,并且我继续使用分层方法,并且希望在代码中有一个公共层。现在,我的处境是这样的:

  • 公共业务逻辑层。
  • 平台特定的数据层(由NoteDataStore接口表示)
  • 平台特定的应用核心层(控制器,如果我可以这样称呼它的话)。
  • 请注意,如果我使用工厂模式或其他类似模式,我可以负担得起每个平台特定的层。因此,工厂方法/类本身可以了解NoteDataStore实现类。但是,业务逻辑层必须不知道任何实现类。

    各层的典型用途如下:

    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在对原始问题的评论中提出的建议。我只是在创建BusinessLogicLayer的时候传递了NoteDataStore的一个实例。

    这个简单的解决方案非常适合我的需要,因为我不需要工厂。我的主要目标是让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应用程序中都使用过它。