Iteratorパターン実装してみた
どーも、ふぎとです。
今回は結城浩『Java言語で学ぶデザインパターン入門』
(SB Creative)を参考にしながら、デザインパターン
のひとつである「Iteratorパターン」を実装していき
ます。
Iteratorパターンとは
Iteratorパターンとは、何かがたくさん集まっている
ときに、それを順番に指示していき、全体をスキャン
していく処理を行うためのものです。(P.2)
例えていえば、「袋に入ったモノの正体をひとつずつ
調べる」というプログラム、という感じかな。
本書ではサンプルプログラムとして、「本棚の中に入
れた本を調べ、その本の名前を順番に表示する」もの
が紹介されています。今回はそこにアレンジを加えて
「ソングリストに入った曲をひとつずつ表示させる」
プログラムをIteratorパターンで書いていこうと思いま
す。
Aggregate(集合体)インターフェース
Aggregateインターフェースは、数え上げを
行うものの「集合体」を表します。(P.3)
ここでは「曲の集合体」を表す「SongAggregate」
というインターフェースを作成します。
public interface SongAggregate {
public abstract SongIterator songIterator();
}
このインターフェースでは、集合体を数えあげる
ためのメソッド「songIterator」のみを宣言します。
Iteratorインターフェース
Iteratorインターフェースは要素の数え上げ
を行うもの、ループ変数のような役割を果た
すものです。
ここでは「SongIterator」を作成します。
public interface SongIterator {
public abstract boolean hasNext();
public abstract Object next();
}
hasNextメソッドは、「集合体」に次の要素があるか
どうか調べるためのものです。またnextメソッドは
次の要素がある場合に、その要素を得ます。
Songクラス
ひとつひとつの「曲」を表すためのクラスです。
public class Song {
private String songName;
public Song(String s) {
this.songName = s;
}
public String getSongName() {
return songName;
}
}
SongListクラス
「曲の集合体」を表現しているクラスです。
SongAggregateインターフェースを実装し、抽象メソッドで
あったsongIteratorメソッドをオーバーライドします。
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メソッドをオーバー
ライドします。
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クラスを作成して実際のリストを作り、スキャン
してみます。
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
Author And Source
この問題について(Iteratorパターン実装してみた), 我々は、より多くの情報をここで見つけました https://qiita.com/FugitHora812/items/8fab627b41f55a454b13著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .