LoginSignup
0
1

More than 3 years have passed since last update.

Iteratorパターン実装してみた

Posted at

どーも、ふぎとです。

今回は結城浩『Java言語で学ぶデザインパターン入門』
(SB Creative)を参考にしながら、デザインパターン
のひとつである「Iteratorパターン」を実装していき
ます。

Iteratorパターンとは

Iteratorパターンとは、何かがたくさん集まっている
ときに、それを順番に指示していき、全体をスキャン
していく処理を行うためのものです。(P.2)

例えていえば、「袋に入ったモノの正体をひとつずつ
調べる」というプログラム、という感じかな。

本書ではサンプルプログラムとして、「本棚の中に入
れた本を調べ、その本の名前を順番に表示する」もの
が紹介されています。今回はそこにアレンジを加えて
ソングリストに入った曲をひとつずつ表示させる
プログラムをIteratorパターンで書いていこうと思いま
す。

Aggregate(集合体)インターフェース

Aggregateインターフェースは、数え上げを
行うものの「集合体」を表します。(P.3)

ここでは「曲の集合体」を表す「SongAggregate」
というインターフェースを作成します。

SongAggregate.java
public interface SongAggregate {
    public abstract SongIterator songIterator();
}

このインターフェースでは、集合体を数えあげる
ためのメソッド「songIterator」のみを宣言します。

Iteratorインターフェース

Iteratorインターフェースは要素の数え上げ
を行うもの、ループ変数のような役割を果た
すものです。

ここでは「SongIterator」を作成します。

SongIterator.java
public interface SongIterator {
    public abstract boolean hasNext();
    public abstract Object next();
}

hasNextメソッドは、「集合体」に次の要素があるか
どうか調べるためのものです。またnextメソッドは
次の要素がある場合に、その要素を得ます。

Songクラス

ひとつひとつの「曲」を表すためのクラスです。

Song.java
public class Song {
    private String songName;

    public Song(String s) {
        this.songName = s;
    }

    public String getSongName() {
        return songName;
    }
}

SongListクラス

「曲の集合体」を表現しているクラスです。
SongAggregateインターフェースを実装し、抽象メソッドで
あったsongIteratorメソッドをオーバーライドします。

SongList.java
public class SongList implements SongAggregate {
    private Song[] songs;
    private int last = 0;

    public SongList(int max) {
        this.songs = new Song[max];
    }

    public Song getSongAt(int id) {
        return songs[id];
    }

    public void appendSong(Song s) {
        this.songs[last] = s;
        last++;
    }

    public int getLength() {
        return last;
    }

    @Override
    public SongIterator songIterator() {
        return new SongListIterator(this);
    }

}

ここではコンストラクタによって、曲を最大max
個まで格納できるSongListインスタンスを定義
しています。
getSongAtメソッドは、id番目の曲を返します。
appendSongメソッドは、配列songs[]の一番後ろに
新たな曲sを格納します。
getLengthは、SongListに入っている曲の数を返す
メソッドです。
そして、オーバーライドしたsongIteratorメソッドでは、
これから作成するSongListIteratorというクラスの
インスタンスを生成し、SongIterator型として返します。

SongListIteratorクラス

実際にSongListクラスの走査(スキャン)を行う
クラスです。SongIteratorインターフェースを実
装し、hasNextメソッド・nextメソッドをオーバー
ライドします。

SongListIterator.java
public class SongListIterator implements SongIterator {
    private SongList songList;
    private int id;

    public SongListIterator(SongList sl) {
        this.songList = sl;
        this.id = 0;
    }

    @Override
    public boolean hasNext() {
        if(id < songList.getLength()) {
            return true;
        }else {
            return false;
        }
    }

    @Override
    public Object next() {
        Song song = songList.getSongAt(id);
        id++;
        return song;
    }

}

以上で、リストを走査する準備は完了です。ここから
Mainクラスを作成して実際のリストを作り、スキャン
してみます。

Main.java
public class Main {
    public static void main(String[] args) {
        //新しくSongListを作成
        SongList songList = new SongList(5);

        //リストに曲を追加
        songList.appendSong(new Song("So What"));
        songList.appendSong(new Song("Freddie Freeloader"));
        songList.appendSong(new Song("Blue In Green"));
        songList.appendSong(new Song("All Blues"));
        songList.appendSong(new Song("Flamenco Sketches"));

        //SongIteratorのインスタンスを生成
        SongIterator song_it = songList.songIterator();

        //曲をひとつずつ調べる
        while(song_it.hasNext()) {
            Song song = (Song)song_it.next();
            System.out.println(song.getSongName());
        }
    }

}

実行結果は以下のようになりました。

So What
Freddie Freeloader
Blue In Green
All Blues
Flamenco Sketches

ちゃんと実行されたようです。やれやれ。

まとめ

つまるところ、Iteratorパターンのポイントは、
SongListを書き直しても、songIteratorメソッドが
存在し、正しいSongIteratorを返してくれれば、Mainメ
ソッドのwhileループは全く変更せずとも動作する

点にあります。要するに、機能の拡張に耐えうる設計に
なっているってことです。まさに「現場の知恵」だなと
いう風に感じます。

今後はこんな調子でGoFのデザインパターン23個、ぼち
ぼちまとめていければと。

では今日はこの辺で。ふぎとでした。

P.S. 「先輩」の皆さま、この記事に対する意見、
補足などあれば遠慮なくコメントくださいm(__)m

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1