Javaにおけるコンテキストオブジェクトパターン:コンテキストデータへのアクセスを簡素化
別名
- コンテキスト
- コンテキストカプセル化
- コンテキストホルダー
- コンテキストをカプセル化
コンテキストオブジェクトデザインパターンの目的
ユーザーまたは処理中のリクエストに関連するコンテキスト(状態と動作)をカプセル化して、Javaアプリケーションコンポーネントを環境の複雑性から切り離します。このデザインパターンは、アプリケーションのコンテキストを効率的に管理するのに役立ちます。
実例を用いたコンテキストオブジェクトパターンの詳細な説明
現実世界の例
多くのサービスが乗客情報にアクセスし、旅程全体で共有する必要がある忙しい空港を想像してみてください。各サービスが個別に乗客の詳細を要求して渡す代わりに、空港は「乗客コンテキストオブジェクト」を使用します。このコンテキストオブジェクトには、身分、フライトの詳細、好みなど、関連するすべての乗客情報が保持されます。チェックイン、セキュリティ、搭乗、カスタマーサービスなどのさまざまなサービスは、このコンテキストオブジェクトにアクセスして、必要に応じて乗客データを取得または更新します。このアプローチにより、サービスを密結合することなく、一貫性のある効率的な情報処理が確保されます。これは、コンテキストオブジェクトデザインパターンがソフトウェアで機能する方法と同様です。
簡単に言うと
コンテキストデータを格納および管理するオブジェクトを作成し、必要に応じてJavaアプリケーションのどこにでもこのコンテキストオブジェクトを渡して、デカップリングされ、クリーンなコードを確保します。
プロトコルに依存しない方法で状態をカプセル化するコンテキストオブジェクトを使用して、アプリケーション全体で共有します。
Javaにおけるコンテキストオブジェクトのプログラミング例
多層Javaアプリケーションでは、A、B、Cなどの異なる層が共有コンテキストから特定の情報を抽出します。各情報を個別に渡すのは非効率です。コンテキストオブジェクトパターンは、この情報を効率的に格納および渡すことで、Javaアプリケーション全体の性能と保守性を向上させます。
ServiceContext
オブジェクトが含むデータを定義します。
@Getter
@Setter
public class ServiceContext {
String accountService;
String sessionService;
String searchService;
}
アプリケーションの一部でコンテキストオブジェクトを作成するために使用されるインターフェースServiceContextFactory
を作成します。
public class ServiceContextFactory {
public static ServiceContext createContext() {
return new ServiceContext();
}
}
最初の層でコンテキストオブジェクトをインスタンス化します。隣接する層は現在の層のコンテキストを呼び出し、その後オブジェクトをさらに構造化します。
@Getter
public class LayerA {
private static ServiceContext context;
public LayerA() {
context = ServiceContextFactory.createContext();
}
public void addAccountInfo(String accountService) {
context.setACCOUNT_SERVICE(accountService);
}
}
@Getter
public class LayerB {
private static ServiceContext context;
public LayerB(LayerA layerA) {
this.context = layerA.getContext();
}
public void addSessionInfo(String sessionService) {
context.setSESSION_SERVICE(sessionService);
}
}
@Getter
public class LayerC {
public static ServiceContext context;
public LayerC(LayerB layerB) {
this.context = layerB.getContext();
}
public void addSearchInfo(String searchService) {
context.setSEARCH_SERVICE(searchService);
}
}
これが、動作中のコンテキストオブジェクトと層です。
@Slf4j
public class App {
private static final String SERVICE = "SERVICE";
public static void main(String[] args) {
//Initiate first layer and add service information into context
var layerA = new LayerA();
layerA.addAccountInfo(SERVICE);
logContext(layerA.getContext());
//Initiate second layer and preserving information retrieved in first layer through passing context object
var layerB = new LayerB(layerA);
layerB.addSessionInfo(SERVICE);
logContext(layerB.getContext());
//Initiate third layer and preserving information retrieved in first and second layer through passing context object
var layerC = new LayerC(layerB);
layerC.addSearchInfo(SERVICE);
logContext(layerC.getContext());
}
private static void logContext(ServiceContext context) {
LOGGER.info("Context = {}", context);
}
}
プログラム出力
08:15:32.134 [main] INFO com.iluwatar.context.object.App -- Context = com.iluwatar.context.object.ServiceContext@5577140b
08:15:32.136 [main] INFO com.iluwatar.context.object.App -- Context = com.iluwatar.context.object.ServiceContext@5577140b
08:15:32.137 [main] INFO com.iluwatar.context.object.App -- Context = com.iluwatar.context.object.ServiceContext@5577140b
Javaでコンテキストオブジェクトパターンを使用する場合
- Javaアプリケーションでコンテキスト情報を抽象化およびカプセル化し、ビジネスロジックを環境固有のコードで乱雑にする必要がない場合。これは、リクエスト固有の情報をカプセル化するためのWebアプリケーション、およびユーザー設定やセキュリティ資格情報を管理するための分散システムで特に役立ちます。
- Webアプリケーションでは、リクエスト固有の情報をカプセル化し、関数またはコンポーネント間で明示的に渡すことなく、アプリケーション全体で簡単にアクセスできるようにします。
- 分散システムでは、実行中のタスク、ユーザー設定、またはセキュリティ資格情報に関するコンテキスト情報をカプセル化し、異なるコンポーネントやサービス間での伝播を容易にします。
Javaにおけるコンテキストオブジェクトパターンの現実世界のアプリケーション
- Webアプリケーションフレームワークは、HTTPリクエストとレスポンスオブジェクト、セッション情報、その他のリクエスト固有のデータをカプセル化するために、多くの場合、コンテキストオブジェクトパターンを使用します。エンタープライズJavaアプリケーションは、このパターンを利用して、トランザクション情報、セキュリティ資格情報、ユーザー固有の設定を異なる層やサービス間で管理および伝播します。
- エンタープライズアプリケーションは、コンテキストオブジェクトを使用して、トランザクション情報、セキュリティ資格情報、ユーザー固有の設定を異なる層やサービス間で管理および伝播します。
- Spring:ApplicationContext
- Oracle:SecurityContext
- Oracle:ServletContext
コンテキストオブジェクトパターンの利点とトレードオフ
利点
- デカップリング:コンポーネントとサービスは、実行環境の特性から切り離され、モジュール性と保守性が向上します。
- 集中化:コンテキスト情報は一箇所に集中されるため、管理、アクセス、デバッグが容易になります。
- 柔軟性:このパターンにより、柔軟で動的なコンテキスト管理が可能になり、環境や要件の変化に適応できます。
トレードオフ
- オーバーヘッド:コンテキストオブジェクトの導入は、特に効率的に実装されていない場合、パフォーマンスのオーバーヘッドにつながる可能性があります。
- 複雑さ:コンテキストオブジェクトが適切に設計されていない場合、膨大で複雑なモノリスになり、管理や理解が困難になる可能性があります。
関連するJavaデザインパターン
- シングルトン:コンテキストオブジェクトは、グローバルなアクセス点を確保するために、多くの場合シングルトンとして実装されます。
- ストラテジー:コンテキストオブジェクトは、カプセル化するコンテキストに基づいて動作を適応させるために、ストラテジーを使用できます。
- デコレーター:コンテキストオブジェクトに動的に責任を追加するために使用できます。