サービスロケーターパターン

サービスロケーターパターン(Service Locator Pattern)は、JNDI クエリを使用してさまざまなサービスを特定して検索したい場合に使用します。特定のサービスの JNDI を検索するコストが高いことを考慮して、サービスロケーターパターンはキャッシュ技術を最大限に活用します。サービスの最初のリクエスト時に、サービスロケーターは JNDI でサービスを検索し、そのサービスオブジェクトをキャッシュします。同じサービスが再度リクエストされた場合、サービスロケーターはキャッシュ内で検索するため、アプリケーションのパフォーマンスを大幅に向上させることができます。以下はこのデザインパターンのエンティティです。

  • サービス(Service)- 実際にリクエストを処理するサービス。このサービスへの参照は JNDI サーバーで見つけることができます。
  • Context / 初期 Context- JNDI Context は、検索するサービスへの参照を持ちます。
  • サービスロケーター(Service Locator)- サービスロケーターは、JNDI 検索とサービスのキャッシュによってサービスを取得するための単一の接点です。
  • キャッシュ(Cache)- キャッシュはサービスの参照を保存し、それらを再利用できるようにします。
  • クライアント(Client)- Client は、ServiceLocator を介してサービスを呼び出すオブジェクトです。

概要

意図

アプリケーション内に、さまざまなサービスやリソースを取得するための一元化されたサービスアクセスポイントを提供するために使用します。

主に解決する問題

  • アプリケーション内でさまざまなサービスやリソースにアクセスする必要がある場合に、サービスアクセスロジックのハードコードを避ける問題を解決します。

使用シーン

  • アプリケーションが複数の外部サービスやリソースにアクセスする必要があり、これらのアクセスロジックを一元管理したい場合。

実装方法

  • サービスロケーターインターフェース:サービスを取得するメソッドを定義します。
  • サービスロケーター実装:サービスロケーターインターフェースを実装し、サービスの検索およびアクセスロジックをカプセル化します。
  • サービスインターフェース:サービスのインターフェースまたは契約を定義します。
  • 具象サービス:サービスインターフェースを実装し、具体的なサービス機能を提供します。

キーコード

  • サービスロケーター:要求されたサービスインスタンスを検索して返すロジックを含みます。
  • サービスインターフェース:サービスの抽象表現を定義します。

適用例

  • エンタープライズアプリケーション:アプリケーションはサービスロケーターを使用して、データベースサービスやメッセージキューサービスなどにアクセスします。

長所

  1. サービスアクセスの分離:サービスアクセスロジックと、サービスを使用するビジネスロジックを分離します。
  2. 一元管理:サービスのアクセスポイントを一元管理するため、保守と拡張が容易です。
  3. 柔軟性:サービスの追加、変更、置換が容易です。

短所

  • パフォーマンスの問題:特に毎回のサービスリクエストで検索を行う場合、サービスロケーターはパフォーマンスのオーバーヘッドを引き起こす可能性があります。
  • 過度な使用:デザインパターンの乱用につながり、システム構造を隠してしまう可能性があります。

使用上の推奨

  • アプリケーションが柔軟かつ保守可能な方法で複数のサービスにアクセスする必要がある場合は、サービスロケーターパターンの使用を検討してください。

注意事項

  • サービスロケーターへの過度な依存は避けてください。システムの依存関係を隠し、デバッグや最適化を困難にする可能性があるためです。

含まれる主要な役割

  1. サービスロケーターインターフェース(Service Locator Interface):

    • サービスを取得するメソッドを定義します。
  2. サービスロケーター実装(Service Locator Implementation):

    • サービスロケーターインターフェースを実装し、サービスの検索およびアクセスロジックをカプセル化します。
  3. サービスインターフェース(Service Interface):

    • サービスの抽象表現を定義します。
  4. 具象サービス(Concrete Service):

    • サービスインターフェースを実装し、具体的なサービス機能を提供します。
  5. クライアント(Client):

    • サービスロケーターを使用して必要なサービスにアクセスします。

サービスロケーターパターンは、一元化されたサービスアクセスポイントを提供することで、サービスアクセスロジックを簡素化し、アプリケーションの柔軟性と保守性を向上させるのに役立ちます。


<

実装

作成しますServiceLocator、InitialContext、Cache、Serviceエンティティを表すさまざまなオブジェクトとして。Service1とService2エンティティサービスを表します。

ServiceLocatorPatternDemoクラスはここではクライアントとして機能し、次を使用してServiceLocatorサービスロケーターデザインパターンをデモンストレーションします。

服务定位器模式的 UML 图

ステップ 1

サービスインターフェース Service を作成します。

Service.java

public interface Service { public String getName(); public void execute(); }

ステップ 2

具象サービスを作成します。

Service1.java

public class Service1 implements Service { public void execute(){ System.out.println("Executing Service1"); } @Override public String getName() { return "Service1"; } }

Service2.java

public class Service2 implements Service { public void execute(){ System.out.println("Executing Service2"); } @Override public String getName() { return "Service2"; } }

ステップ 3

JNDI クエリ用に InitialContext を作成します。

InitialContext.java

public class InitialContext { public Object lookup(String jndiName){ if(jndiName.equalsIgnoreCase("SERVICE1")){ System.out.println("Looking up and creating a new Service1 object"); return new Service1(); }else if (jndiName.equalsIgnoreCase("SERVICE2")){ System.out.println("Looking up and creating a new Service2 object"); return new Service2(); } return null; } }

ステップ 4

キャッシュ Cache を作成します。

Cache.java

import java.util.ArrayList; import java.util.List; public class Cache { private List<Service> services; public Cache(){ services = new ArrayList<Service>(); } public Service getService(String serviceName){ for (Service service : services) { if(service.getName().equalsIgnoreCase(serviceName)){ System.out.println("Returning cached "+serviceName+" object"); return service; } } return null; } public void addService(Service newService){ boolean exists = false; for (Service service : services) { if(service.getName().equalsIgnoreCase(newService.getName())){ exists = true; } } if(!exists){ services.add(newService); } } }

ステップ 5

サービスロケーターを作成します。

ServiceLocator.java

public class ServiceLocator { private static Cache cache; static { cache = new Cache(); } public static Service getService(String jndiName){ Service service = cache.getService(jndiName); if(service != null){ return service; } InitialContext context = new InitialContext(); Service service1 = (Service)context.lookup(jndiName); cache.addService(service1); return service1; } }

ステップ 6

使用してServiceLocatorサービスロケーターデザインパターンをデモンストレーションします。

ServiceLocatorPatternDemo.java

public class ServiceLocatorPatternDemo { public static void main(String[] args) { Service service = ServiceLocator.getService("Service1"); service.execute(); service = ServiceLocator.getService("Service2"); service.execute(); service = ServiceLocator.getService("Service1"); service.execute(); service = ServiceLocator.getService("Service2"); service.execute(); } }

ステップ 7

プログラムを実行して、出力結果:

Looking up and creating a new Service1 object
Executing Service1
Looking up and creating a new Service2 object
Executing Service2
Returning cached  Service1 object
Executing Service1
Returning cached  Service2 object
Executing Service2
その他の拡張