yynsmk's tech blog

何でもできる=何にもできない

IteratorパターンとAdapterパターンのメリットとは?

はじめに

とあるエンジニアの方からデザインパターンは知っておいた方がいいと聞いたので勉強し始めました。
使用する教材は有名な「Java言語で学ぶデザインパターン入門」です。

この本は第一部から第十部まであるのですが、この記事では第一部についてまとめました。
第一部で登場するデザインパターンは以下の2つです。

  • Iteratorパターン

  • Adapterパターン

デザインパターンとは?

デザインパターンとはGoF(有名な4人らしい)が考えた23個の設計パターンのことです。
デザインパターンに当てはめることで、再利用しやすいプログラムを作れますし、知っているだけでもプログラムの構造について議論する時に役立ちます。

Iteratorパターン

Iteratorパターンはループ変数の働きを抽象化したもので、集合体の各要素を順に指し示していくパターンです。

読んでいる途中は、イテレータをわざわざ実装する意味があるのか?for文で良くない?
と思っていたのですが、読み終えてそのメリットが分かりました。

Iteratorパターンのメリット

for文を使う場合

数え上げる側が集合体クラスの実装(配列なのか、ベクトルなのかなど)について知っておく必要があります。

イテレータを使う場合

集合体クラスに対応したイテレータクラスを用意しておくと、そのイテレータインスタンスを使って数え上げられます。
数え上げる側は集合体クラスの実装については知らなくても問題ありません。

つまり!実装に依存しないプログラムを組める=クラスを再利用しやすい、 これがイテレータを実装するメリットです。

Adapterパターン

AdapterはWrapperともいい、「すでにあるプログラム」と「必要としている機能」とのずれを埋めるようなデザインパターンです。
すでにあるプログラムを利用して、必要としている機能を実現します。
Adapterパターンの実装には以下の2種類があります。

  • 継承を使う(すでにあるプログラムを継承してそのメソッドを使う)

  • 委譲を使う(すでにあるプログラムのインスタンスを作成し、インスタンスを通してメソッドを使う)

継承使ったAdapterパターンのプログラム

継承を使う方のサンプルプログラムを作ってみました。(デザインパターンを学習するには自分で例を考えてみるのが良いらしいです)

Adaptee.java
すでにあるプログラム。
引数の数値を標準出力する機能を持つ。

public class Adaptee {
    public void printNum(int num) {
        System.out.println(num);
    }
}

Target.java
必要としているインタフェース・機能。
引数の文字列を数値に変えて標準出力する機能を持つ。

public interface Target {
    public abstract void printStringToNum(String num);
}

Adapter.java
すでにあるプログラムと必要としている機能とのずれを埋めるアダプター。
すでにある機能printNum()を使って、必要な機能printStringToNum()を実現する。

public class Adapter extends Adaptee implements Target {
    public Adapter() {
        super();
    }
    public void printStringToNum(String num) {
        printNum(Integer.parseInt(num));
    }
}

Main.java
新たなインタフェースを使うクラス。

public class Main {
    public static void main(String[] args) {
       Target target = new Adapter();
       target.printStringToNum("12");
    }
}

この例は簡単で、すでに数値を表示するプログラムAdaptee.javaがあって、それには一切手を加えず、文字列を数値として表示するような機能Target.javaを使えるようにするものです。
ポイントはprintStringToNum()の中で、スーパークラスのprintNum()を呼び出している点です。 また、Mainクラスの中でAdapterインスタンスをTarget型の変数に格納して、Targetのインタフェースを使っている点も要チェックです。

Adapterパターンのメリット

Adapterパターンは、すでにテスト済みのプログラムがあり、それを新たなAPIに対応させる場合に使われます。
一見すでにあるプログラムを修正する方が簡単そうに見えますが、そうするとせっかくテスト済みだったプログラムをもう一回テストしないといけなくなって面倒です。
新たにAdapterを作った場合はテストするのはAdapterのみで済むのでバグも発見しやすくなります。

おわりに

第一部を読んでみて、デザインパターンはクラスの再利用化を促進するためにあって、そのためには抽象クラスやインタフェースを積極的に使っていかんとだめなのねって感じです。
第二部以降も読み進みてまとめていこうと思います。