5

私の問題は、Java のインターフェイスが静的メソッドを許可していないという事実に起因することを述べることから始めたいと思います。SO でのこの理由についての議論がありました (ここでは、たとえば)。だから、それにこだわらないようにしましょう。インターフェイスがそれ自体のインスタンス (むしろその実装) を作成し、それを返す方法を探しています。Singleton パターン、Factory および AbstractFactory パターンをいじっても、まだ目標を達成できません。

私がしようとしていることを詳しく説明するために-これが私のインターフェースです:

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);
}

そして、これが私のビジネス ロジック レイヤーです。

public class BusinessLogicLayer {

    public BusinessLogicLayer(){
        /*
         * GOAL: To get an instance of NoteDataStore here,
         *  without being aware of the implementation class.
         */
    }

}

私は次のようなファクトリーパターンを使用しようとしました:

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ます。

NoteDataStore = new NoteDataStoreFactoryImpl().getDataStoreInstance();

どうすればこれを回避できますか? 使用する正確な実装クラスに関して BusinessLogicLayer を暗闇に保つにはどうすればよいですか?


編集:私の問題のより詳細な背景

回答のいくつかは、Spring などのフレームワークの使用を示唆しています。残念ながら、このアプリケーションはさまざまなモバイル プラットフォーム (Android、Blackberry、JavaME) を対象としているため、そうすることができません。元の質問でこれを明確にする必要がありました-そうしなかったことをお詫びします。

私の主な意図は、プラットフォーム間でアプリを提供することです。UI、データベース アクセス、HTTP トランスポート レイヤーなどは、プラットフォームごとに特別にコーディングする必要があります。ただし、ビジネス ロジックは単純なので、すべてのプラットフォームで共通のレイヤーを保証できます。ビジネス ロジック層を JAR ライブラリとして配布する予定です。解析およびフレーミング レイヤー (JSON/XML 用) も同様です。

これについては SO で既に議論されています (私がこの道をたどるべきかどうかについて) - Logic Code reuse。ただし、これで問題ないと仮定し、レイヤード アプローチを進めて、コード内で 1 つのレイヤーを共通にするつもりです。今、私の状況は私が持っているようなものです:

  1. 共通のビジネス ロジック層。
  2. NoteDataStoreプラットフォーム固有のデータ層 (インターフェースで表される)
  3. プラットフォーム固有のアプリケーション コア レイヤー (コントローラー、そう呼ぶ場合もあります)。

Factory パターンなどを使用する場合、各プラットフォームに固有のレイヤーを使用する余裕があることに注意してください。NoteDataStoreしたがって、ファクトリ メソッド/クラス自体が実装クラスについて知ることができます。ただし、ビジネス ロジック層は実装クラスを認識しない必要があります。

さまざまなレイヤーの一般的な使用法は次のとおりです。

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();
    }
}

このシナリオの処理方法に関する情報はありますか?

4

5 に答える 5

5

クラスは、外部からファクトリ インスタンスを受け入れる必要があります。自分でインスタンスを作成している場合、何も達成しません。ここでは正しいです。

ここにはいくつかのテクニックがあります。一般に、それらは制御の反転または略して IoCと呼ばれる非常に一般的なものに属します。また、「Inversion of Control Containers」または IoCC について知っておくと役立ちます。たとえば、Java には Spring があります。ここを読んでください。他の人については、本物のJavaの人に聞いてください:)

こちらの記事もご覧ください。

于 2011-07-25T04:38:44.590 に答える
2

実装を返したい場合は、匿名の内部クラスで行うことができます

NoteDataStore myImplementation = new NoteDataStore (){
//Implement methods here
};
于 2011-07-25T04:32:58.357 に答える
0

元の質問へのコメントで@Ray Tayekが提供した提案に最終的に行きました。NoteDataStoreの作成時にのインスタンスを渡すだけBusinessLogicLayerです。

Factory は実際には必要ないため、この単純なソリューションは私のニーズに非常に適しています。私の主な目的は、BL レイヤーが使用するインターフェイスの正確な実装クラスを認識しないようにすることでした。現在、ファクトリの代わりに、インターフェイスの具体的な実装を作成し、それらを BL レイヤーに提供するのは、コアの「コントローラー」レイヤーです。これは完璧です!

これがコードスニペットです。

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
    }

}
于 2011-07-27T06:27:16.107 に答える
0

Guice や Spring などの IoC/依存性注入フレームワークを見たことがありますか? それらはあなたが探しているものには重すぎるかもしれませんが、あなたが説明した問題を確実に解決します. これらを使用すると、すべてのビジネス レイヤー コードをインターフェイスに対して記述し、実際の実装を IoC フレームワークを介して定義できます。私は個人的に Spring の大ファンであり、過去 6 年以上に作成したほぼすべての Java アプリで Spring を使用してきました。

于 2011-07-25T04:41:13.400 に答える