Javaにおけるレジストリパターン:Javaオブジェクトの中央制御メカニズムの実装
レジストリデザインパターンの目的
レジストリデザインパターンは、オブジェクトのグローバルな集合の作成と管理を集中化し、単一アクセスポイントを提供し、制御されたインスタンス化を保証します。
現実世界の例を用いたレジストリパターンの詳細な説明
現実世界の例
大企業では、ラップトップ、デスクトップ、サーバー、ソフトウェアライセンスなどのIT資産の管理は困難な場合があります。このプロセスを合理化するために、企業はレジストリとして機能する中央IT資産管理システムを使用します。
- このシステムは、すべてのIT資産に関する情報の登録、追跡、取得のための単一アクセスポイントを提供します。
- 新しいデバイスまたはソフトウェアが調達されると、シリアル番号、購入日、保証期間、割り当てられたユーザーなどの詳細情報とともにシステムに登録されます。
- ITスタッフは、システムを照会して任意の資産の詳細を取得し、その現在の状態を確認し、必要に応じて情報を更新できます。
- この中央管理により、資産の効率的な利用とメンテナンスが促進され、ソフトウェアライセンスへの準拠が保証され、アップグレードや交換の計画が容易になります。
このアナロジーでは、IT資産管理システムはレジストリとして機能し、組織内のIT資産に関するライフサイクルの管理とグローバルなアクセスを提供します。
簡単に言うと
レジストリは、他のオブジェクトが共通のオブジェクトやサービスを見つけるために使用できる、よく知られたオブジェクトです。
wiki.c2.comによると
レジストリは、キーとオブジェクト間のグローバルな関連付けであり、オブジェクトはどこからでもアクセスできます。キーとオブジェクトを受け取ってレジストリにオブジェクトを追加するメソッドと、キーを受け取ってそのキーに対応するオブジェクトを返すメソッドの2つのメソッドが含まれています。これはマルチトンパターンに似ていますが、レジストリ内のオブジェクトのみにインスタンスを制限しません。
Javaにおけるレジストリパターンのプログラミング例
レジストリデザインパターンは、オブジェクトが格納され、それらへのグローバルなアクセスポイントを提供する、ソフトウェア設計でよく知られているパターンです。このパターンは、グローバルなオブジェクトのコレクションを管理する必要がある場合、オブジェクトの作成をその使用から切り離す必要がある場合、オブジェクトのライフサイクルを制御する必要がある場合、そしてオブジェクトの冗長な作成を避ける必要がある場合に特に役立ちます。
まず、Customer
レコードがあります。これは、レジストリに格納されるオブジェクトを表します。各Customer
には、id
とname
があります。
public record Customer(String id, String name) {
@Override
public String toString() {
return "Customer{"
+ "id='" + id + '\''
+ ", name='" + name + '\''
+ '}';
}
}
次に、CustomerRegistry
クラスがあります。このクラスは、Customer
オブジェクトが格納される実際のレジストリです。顧客を追加および取得するメソッドを提供します。CustomerRegistry
はシングルトンであり、アプリケーション内にそのインスタンスは1つだけです。
public final class CustomerRegistry {
@Getter
private static final CustomerRegistry instance = new CustomerRegistry();
private final Map<String, Customer> customerMap;
private CustomerRegistry() {
customerMap = new ConcurrentHashMap<>();
}
public Customer addCustomer(Customer customer) {
return customerMap.put(customer.id(), customer);
}
public Customer getCustomer(String id) {
return customerMap.get(id);
}
}
最後に、App
クラスがあります。このクラスは、CustomerRegistry
の使用方法を示しています。2つのCustomer
オブジェクトを作成し、それらをCustomerRegistry
に追加してから、それらを取得します。
public class App {
private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
public static void main(String[] args) {
CustomerRegistry customerRegistry = CustomerRegistry.getInstance();
var john = new Customer("1", "John");
customerRegistry.addCustomer(john);
var julia = new Customer("2", "Julia");
customerRegistry.addCustomer(julia);
LOGGER.info("John {}", customerRegistry.getCustomer("1"));
LOGGER.info("Julia {}", customerRegistry.getCustomer("2"));
}
}
この例では、CustomerRegistry
はCustomer
オブジェクトへのグローバルなアクセスポイントを提供します。これにより、これらのオブジェクトを集中管理し、再利用と共有を促進し、コンポーネント間のデカップリングを容易にすることができます。
この例を実行すると、次の出力が生成されます。
09:55:31.109 [main] INFO com.iluwatar.registry.App -- John Customer{id='1', name='John'}
09:55:31.113 [main] INFO com.iluwatar.registry.App -- Julia Customer{id='2', name='Julia'}
Javaでレジストリパターンを使用する場合
- グローバルなオブジェクトのコレクションを管理する必要がある場合。
- オブジェクトの作成をその使用から切り離す必要がある場合。
- サービスやリソースなどのオブジェクトのライフサイクルを制御する必要がある場合。
- オブジェクトの冗長な作成を避けたい場合。
Javaにおけるレジストリパターンの現実世界のアプリケーション
- エンタープライズアプリケーションでのデータベース接続の管理。
- モジュール式アプリケーションでサービスまたはコンポーネントを登録および取得するためのセントラルリポジトリを提供する場合。
- アプリケーションのさまざまな部分がアクセスできる中央設定レジストリを作成する場合。
レジストリパターンの利点とトレードオフ
利点
Javaでレジストリパターンを採用することの主な利点
- オブジェクト管理を集中化し、アプリケーションのメンテナンスを容易にします。
- オブジェクトの再利用と共有を促進し、メモリフットプリントと初期化時間を削減できます。
- コンポーネント間のデカップリングを容易にします。
トレードオフ
- 効率的に実装されていない場合、ボトルネックになる可能性があります。
- レジストリがフォールトトレラントになるように設計されていない場合、単一障害点が発生する可能性があります。
- オブジェクトのライフサイクルの管理の複雑さが増加します。
関連パターン
- シングルトン:レジストリのインスタンスが1つしかないことを保証するために、レジストリと組み合わせて使用されることがよくあります。
- ファクトリ:オブジェクトがレジストリから取得される場合に必要なインスタンス化ロジックをカプセル化するために使用されます。
- サービスロケーター:意図と構造が類似したパターンで、レジストリと交換可能に使用されることがよくあります。
- 依存性注入:依存関係を管理するための代替方法を提供し、レジストリの必要性を置き換える場合があります。
- マルチトン:複数のインスタンスを管理しますが、キーに基づいて行い、キーごとに1つのインスタンスのみを保証するという点で、レジストリに似ています。