- 恥ずかしいデザインパターン勉強会 #2 - connpass をやりました
- 第2回で前より上手く進行できるかなと思ったんですが、ぜんぜんそんなことなかったっす
第1部より
- IteratorパターンとAdapterパターンを勉強しました
- ライブコーディングのログです↓
#hazukac 今日の会場WiFiのSSID、榛名さん改二おめでとう仕様だwww
— ( ´_ゝ`) (@otiai10) 2014, 7月 30
Iteratorパターン
- 要素の集合の要素ひとつひとつにアクセスしたいときにforを使うけれど
- 集合を持つクラスが要素の集合をどのように持っているか知りたくない
- どのような走査をするかの内部実装を知りたくない
- (アプリケーションがそれを知ると、走査方法などが変わったときに変更範囲が増える)
ポイント
- 集合(Aggregateと言ってもよい)は、自身の要素(直下でなくてもよい)を走査するためのインスタンス(Iteratorと言ってもよい)を提供できる
- アプリケーションは集合の要素の終端などを知る必要はなく、IteratorのhasNextやnextといったような任意の名前のメソッドを提供することで、Iteratorの定義のみが過不足無い走査の実装を知り、それを提供できる
- 走査方法など細かく修飾したIteratorを作ることもできる
public class Main { public static void main(String[] args) { Building roppongiHills = new RoppongiHills(); CompanyIterator cItr = roppoingiHills.getCompanyIterator(); while (cItr.hasNext()) { Company company = cItr.getNext(); System.out.println(company.getName()); } ShopIterator sItr = roppoingiHills.getShopIterator(); while (sItr.hasNext()) { Shop shop = sItr.getNext(); System.out.println(shop.getFloor()); } } }
Adapterパターン
- あるリソースとそれを使うアプリケーションがあり
- リソースの入れ替えや、アプリケーションからの要求が変わった場合
- リソースへのアクセスを提供するインターフェースを変更すると、そのリソースを利用する全てのアプリケーションへ広く影響を与えかねない
- アプリケーションにおいて変更を吸収するコードを書くと、将来および類似のアプリケーションの要求変更に対し変更すべき範囲が増えてしまう
実装例1: クラス継承を使う
ポイント
- 既存のリソースを継承し
- 親の旧いインターフェースを叩きつつ、新たな要求を満たすインターフェースを提供する
- まさにラップする(包み込む)イメージ
public class NewAPI extends OldAPI { public int newX(int n) { return this.oldX(n) + 2; } public int newY(int m) { return this.oldY(m) - 2; } }
実装例2: 委譲を使う
ポイント
- 既存のリソースをプロパティとして保持し
- そのプロパティのインターフェースを叩きつつ、新たな要求を満たすインターフェースを提供する
public class NewAPI { private OldAPI old = new OldAPI(); public int newX(int n) { return this.old.oldX(n) + 2; } public int newY(int m) { return this.old.oldY(m) -2; } }
- 既存のOldAPに何かしらの制約があり、NewAPIはその制約に関わりたくないときは、比較的ラクに実装できるのではないか
雑感
- 「僕自身が勉強を継続できる」という目的を確実に達成できていて手応えを感じる
- 参加して頂いている皆さんのツッコミで学ぶこともめちゃくちゃ多い
- ほんとうにありがとうございますm( )m
- 増補改訂版Java言語で学ぶデザインパターン入門