【Flutter/Dart】Adapterパターン
Adapterパターンは、既存のクラスのインターフェースが要求する仕様と一致しない場合に、既存のクラスを変更せずに機能させるデザインパターンです。
ACアダプターと同じ原理
ACアダプターはデバイスのプラグ(海外製品など)と家庭用コンセント(日本基準)との間に介在し、両者の形状が違ってもデバイスをコンセントに接続することができます。このアダプターがあることで、デバイスはコンセントから安全に電力を供給できます。
これがアダプターパターンの役割です。2つの異なるインターフェースを持つクラスやシステムが互いにコミュニケーションをとることができないとき、アダプターパターンはその間に立って、互換性のないインターフェースを変換し、クラスやシステムがうまく働くようにします。
具体的には、アダプタークラスは既存のクラスのインターフェースをラップ(取り囲み)し、新しいインターフェースを提供します。その結果、新しいインターフェースが他のクラスやシステムと一緒にうまく働くことができるようになります。
効果的に利用されるシナリオ
ライブラリのインターフェースが一致しない場合
3rdパーティーのライブラリを導入したいが、そのインターフェースが適合しない場合に、それらを繋ぐアダプターパターンを利用できます。
複数ソースからのデータ統合
アプリが複数のデータソースから情報を取得する場合に、アダプターパターンを使用してデータを統一された形式に変換します。
互換性のないAPIの結合
異なる種類のAPIを利用する場合に、その差異を吸収したアダプターパターンを作成すると効果的です。
サンプルコード
データを異なる形式から取得するケースを例に、サンプルコードを書いてみます。
取得するのはJSONとXMLです。
しかし、我々のアプリはXMLしか対応していないとします。
こちらはXMLデータ形式を取得するクラスです。
/// XMLからデータを取得するクラス
class XMLAdaptee {
String getXmlData() {
return "<data>This is XML data</data>";
}
}
こちらは本筋のXMLをJSONに変換するAdapterクラスです。
/// Adapterクラス
class Adapter {
final XMLAdaptee _adaptee;
Adapter(this._adaptee);
String getJsonData() {
String xmlData = _adaptee.getXmlData();
// ここでは単純にタグを除去する処理にしています。
// 実際にはXMLを適切に解析し、JSONに変換するロジックが必要です。
String jsonData =
xmlData.replaceAll('<data>', '').replaceAll('</data>', '');
return '{"data": "$jsonData"}';
}
}
最後に、クライアントコードです。
void main() {
// XML形式しか扱えないアプリがJSON形式のデータと直面しました。
XMLAdaptee xmlAdaptee = XMLAdaptee();
// Adapterを使うことでXMLデータをJSONデータに変換できます。
Adapter adapter = Adapter(xmlAdaptee);
// JSON形式でデータを取得します。
String jsonData = adapter.getJsonData();
// クライアントはXMLデータの存在を知らずに、JSONデータを利用できます。
log(jsonData); // [log] {"data": "This is XML data"}
}
ログを見るとJSON形式に変換されているのが分かります。
[log] {"data": "This is XML data"}
Adapterクラスを利用することで、JSONしか扱えないアプリがXMLからデータを取り込めるようになったのが分かります。