1. Iteratorパターン 2
- 2012/04/26 一部修正しました
- 1.1 Itaratorパターンとは
- 1.2 サンプルケース
- 1.2 実習課題1
- 1.2 実習課題2
- 1.2 実習課題3
- 1.3 Iterator パターンのまとめ
(実習課題1)
「Teacher」抽象クラスを継承する MyTeacher クラスと、「StudentList」クラスを拡張した MyStudentList クラスを設計しクラス図を作成しなさい。また、これらのクラスを実装し、 下記のMain クラスを実行しなさい。この2つのクラス以外のクラスやインタフェースを自由に追加しても問題ありません。 MyTeacher クラスの callStudents メソッドでは、あなたのクラスの生徒を順番に標準出力に出力するようにしなさい。
あなたのクラスの生徒は、
- 赤井亮太 男
- 赤羽里美 女
- 岡田美央 女
- 西森俊介 男
- 中ノ森玲菜 女
の5人とします。
public class Main{ public static void main(String args[]){ Teacher you = new MyTeacher(); you.createStudentList(); you.callStudents(); } }
回答例1
ここでは、回答例として、下記のように MyTeacher クラスを実装したものとします。
public class MyTeacher extends Teacher{ private StudentList studentList; public void createStudentList(){ studentList = new StudentList(5); studentList.add(new Student("赤井亮太",1)); studentList.add(new Student("赤羽里美",2)); studentList.add(new Student("岡田美央",2)); studentList.add(new Student("西森俊介",1)); studentList.add(new Student("中ノ森玲菜",2)); } public void callStudents(){ int size = studentList.getLastNum(); for(int n=0;n<size;n++){ System.out.println(studentList.getStudentAt(n).getName()); } } }
MyStudentList クラスは作成せず、与えられた StudentList を利用することにしました。 これは、あくまでも回答例であり、次節で紹介する Iterator パターンを利用した場合の説明をスムーズに進めるためのものです。 したがって、この問題にはさまざまな回答があるでしょうし、どれが正解で、どれが間違いなどというものはありません。
さて、どのような設計になったでしょう。あなたは、あなたなりのやり方で、 callStudents() メソッドを実装しました。そして、このメソッドを利用して、 毎朝出席を取ることにも慣れてきました。ところが学校側から「名簿が古くなったので、 新しい形式のものに変えようと思います。新しい名簿は、java.util.Vector クラスを利用したものです。」 との通達があり、新しい名簿が渡されました。新しい名簿は、以下のように与えられます。
import java.util.Vector; public class NewStudentList{ protected Vector<Student> students; public void add(Student student){ students.add(student); } public Student getStudentAd(int index){ return students.get(index); } }
どうでしょう、うまく対応できそうでしょうか?回答例のような実装をしていると、 せっかく慣れてきた日々の仕事を変えなければならないでしょう。 不安になったあなたは隣のクラスのベテランの先生に相談に行きました。
あなた | : | このままでは先生を続けていく自信がありません。なにかいい方法ありませんか? |
ベテラン | : | あれ?言ってなかったっけ? |
あなた | : | 何をですか? |
ベテラン | : | 私は Iterator パターンを利用して名簿をうまく利用してるよ。 |
あなた | : | い、いてれーた?何ですかそれ? |
ベテラン | : | いやなに、簡単簡単。 |
といってベテラン先生は、図を取り出しました。
ベテラン | : | これは、Iterator パターンを表した図だよ。Iterator パターンでは、 何らかの集約体が必ずAggregate インタフェースを実装するようにしているんだ。 Aggregate とは、集約を意味する単語で、Aggregate インタフェースでは Iterator インタフェースの実装クラスを返す、iterator() というメソッドを定義しているだけ。 Iterator インタフェースには、集約体を操作するために必要なメソッドとして、 この集約体に次の要素が存在するかしないかを boolean 型で返す hasNext() メソッドと、次の要素を返す next() メソッドを定義したよ。 next() メソッドの返り値は、Object 型とする。この2つのインタフェースのソースコードは、 それぞれ以下のようになるね。 |
public interface Aggregate{ public Iterator iterator(); }
public interface Iterator{ public boolean hasNext(); public Object next(); }
なるほど、ここまでは、そんなに難しい話ではないようです。
ベテラン | : | 次に、これをもっと具体的に考えてみよう。例えば、今回のケースだと、 具体的な集約体をあらわすクラスはどのクラスになると思う? |
あなた | : | StudentList クラスでしょうか? |
ベテラン | : | そうだね、今回君が自由に作成することができる集約体は、 StudentList クラスを拡張したクラスだ。これを MyStudentList クラス と名づけよう。これが、上の図の ConcreteAggregate に当てはまるね。 この ConcreteAggregate の役割を果たすためには、MyStudentList クラスは、 Aggregate インタフェースを実装する必要があるんだ。 |
あなた | : | なるほど、ソースコードにすると次のような感じでしょうか? |
public class MyStudentList extends StudentList implements Aggregate{ public Iterator iterator(){ return ・・・; //Iteratorオブジェクトを返す。 } }
あなた | : | Iteratorオブジェクトを返すには、ここで Iterator オブジェクトを作成するようにしなければなりませんね。 Iterator インタフェースをインスタンス化することはできないし・・・。 上の図で言う ConcreteIterator の役割を果たすクラスを作成する必要があるわけですか? |
ベテラン | : | かわいい顔してなかなか鋭いね。ConcreteAggregate クラスと ConcreteIterator クラスは対になっているんだよ。 ConcreteAggregate クラスにあわせて ConcreteIterator クラスを作成する必要がある。 では、今回のケースについてクラス図を作成してみよう。 |