Adapter Pattern
アダプターパターンについて勉強した内容を整理します。
アダプターパターンとは互換性のないインターフェース間での通信を可能にし、既存のクラスを再利用することができるようにするといったところでしょうか。アダプターと聞くと変換器のイメージをします。
以前スマホのバッテリーを買い替えたときにそれがType-Cしか利用できなくて、それまではmicroUSB(B)で充電していたのでアダプターを買って先端につなげて使ってました。
上記のように既に使用している物を、他でも同じように使用できるようにつなぎ合わせるものとのイメージを持っています。
構成
chatGPTに何度か解説をお願いいしたら以下のように返ってきました。
アダプターパターンは、以下の主な要素から構成されます:
Target(ターゲット): これは、クライアントが期待するインターフェースを定義します。クライアントはこのインターフェースを使用してオブジェクトとやり取りします。
Adaptee(アダプティ): これは、既存のクラスやコンポーネントです。クライアントは直接Adapteeを使用することはできません。
Adapter(アダプタ): これは、AdapteeのインターフェースをTargetのインターフェースに変換する役割を担います。AdapterはTargetインターフェースを実装し、その内部でAdapteeのメソッドや機能を呼び出します。
実装
上記と学習した内容をもとにクラス図を書き実装してみます。
-
Target
public interface ICreate { void Create(); }
-
Adaptee
今回は、Adapteeは標準ライブラリで提供されているFileクラス、Directoryクラスを使用します。
Fileクラス、Directoryクラスがそれぞれ持っているファイル、ディレクトリの作成メソッドをAdapterクラスで呼び出し、Targetのインターフェースに変換します。
-
Adapter(例:CreateDirectoryクラス)
public class CreateDirectory : ICreate { public void Create() { var desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); var directoryPath = Path.Combine(desktopPath, "アダプターパターンフォルダ"); // フォルダを作成する Directory.CreateDirectory(directoryPath); } }
-
Main
internal class Program { static void Main(string[] args) { var createDirectory = new CreateDirectory(); var createFile = new CreateFile(); Create〇〇(createDirectory); Create〇〇(createFile); } static void Create〇〇(ICreate obj) { obj.Create(); } }
メリット
ではこのパターンのメリットはなんなのか。chatGPTはこのように教えてくれた。
1.既存のクラスを再利用: 既存のクラスやライブラリがある場合、アダプターパターンを使用してその機能を再利用できます。既存のコードを変更することなく、新しいインターフェースに適合させることができます。
2.互換性のないインターフェースの連携: アダプターパターンにより、互換性のないインターフェース間での通信を実現できます。既存のクラスやコンポーネントが必要なインターフェースを持っていなくても、アダプターを介して相互作用できます。
3・システムの柔軟性: アダプターパターンは、アプリケーションの柔軟性を高めます。新しいクラスやコンポーネントが追加された場合でも、アダプターを使用してそれらを既存のコードに統合できます。
今回実装例はあまり良くなかったかもしれませんが(既存がライブラリのメソッドなので)、実装してみてAdapterを使用すると、既存のコードを変更することなく別クラスで使用することができる点はメリットかなと思いました。
また、すでにテストコードが書かれたクラス、メソッドであった場合、書き換えてしまうとそちらの修正コストもかかりますが、Adapterパターンを使用すればその心配はなくなりますね。