Iterator
デザインパターンとは
デザインパターンとはオブジェクト思考開発における先人たちが作り上げてきた便利な設計図です。
Gang of Four通称Gofが1994年に出版した『オブジェクト指向における再利用のためのデザインパターン』の中で23個の設計図が紹介されています。
Note
デザインパターンのサンプルコードはSwift4でまとめます。
イテレータパターンとは?
Itaratorパターンは要素の集まりを持つオブジェクトに対して順番にアクセスを提供するためのパターンです。
下記のようなコードではiがIteratorの役割を持っています。
for i in 0...10{}
iの動きは0から10まで最初から順番にスキャンをしています。ここで使われているiの動きを抽象化したものがIteratorパターンです。
サンプルコード
サンプルコードでは、本棚にある本に順番にアクセスして名前を取得するプログラムを作成しました。
Protocol
プロトコルは2つあります。この2つの基本概念は今回のサンプル以外でもそのまま使うことができます。
Aggregate
要素の塊を保有する対象のクラスに準拠させることで、要素を順番に取得できるようにします。・
protocol Aggregate {
func iterator() -> Iterator
}
Iterator
戻り値から予測できるかと思いますが、次のオブジェクトがあるかをhasNextで判定し、存在すればnextメソッドを使って取得します。
protocol Iterator {
func hasNext() -> Bool
mutating func next() -> Any
}
Bookクラス(取り出す実体)
class Book {
let name: String
init(name: String) {
self.name = name
}
}
本棚クラス
このクラスで注目すべきはiterateメソッドです。自分を別のクラス渡しています。
本棚クラスの中で処理をするのではなく、別のクラスで行うことでクラス間の結合を弱めクラスを1つの部品として再利用しやすくしています。
class BookShelf: Aggregate {
var books:[Book] = []
func appendBook(book: Book){
books.append(book)
}
func getBook(index: Int) -> Book {
return books[index]
}
func iterator() -> Iterator {
return BookShelfIterator(bookShelf: self)
}
}
本棚イテレータ
class BookShelfIterator: Iterator {
private let bookShelf: BookShelf
private var index = 0
init(bookShelf: BookShelf) {
self.bookShelf = bookShelf
}
func hasNext() -> Bool {
if bookShelf.books.count > index {
return true
}
return false
}
func next() -> Any {
let book = bookShelf.getBook(index: index)
index += 1
return book
}
}
呼び出し元
let bookShelf = BookShelf()
//本棚に本を追加
bookShelf.appendBook(book: Book(name: "マンガ"))
bookShelf.appendBook(book: Book(name: "小説"))
bookShelf.appendBook(book: Book(name: "技術書"))
//作った本棚でイテレータを作成
let iterator = BookShelfIterator(bookShelf: bookShelf)
while(iterator.hasNext()){
let book = iterator.next()
if let book = book as? Book{
print(book.name)
}
}
コンソール
マンガ
小説
技術書
コード一覧
import UIKit
protocol Aggregate {
func iterator() -> Iterator
}
protocol Iterator {
func hasNext() -> Bool
func next() -> Any
}
class Book {
let name: String
init(name: String) {
self.name = name
}
}
class BookShelf: Aggregate {
var books:[Book] = []
func appendBook(book: Book){
books.append(book)
}
func getBook(index: Int) -> Book {
return books[index]
}
func iterator() -> Iterator {
return BookShelfIterator(bookShelf: self)
}
}
class BookShelfIterator: Iterator {
private let bookShelf: BookShelf
private var index = 0
init(bookShelf: BookShelf) {
self.bookShelf = bookShelf
}
func hasNext() -> Bool {
if bookShelf.books.count > index {
return true
}
return false
}
func next() -> Any {
let book = bookShelf.getBook(index: index)
index += 1
return book
}
}
let bookShelf = BookShelf()
//本棚に本を追加
bookShelf.appendBook(book: Book(name: "マンガ"))
bookShelf.appendBook(book: Book(name: "小説"))
bookShelf.appendBook(book: Book(name: "技術書"))
//作った本棚でイテレータを作成
let iterator = BookShelfIterator(bookShelf: bookShelf)
while(iterator.hasNext()){
let book = iterator.next()
if let book = book as? Book{
print(book.name)
}
}
参考文献
[iOS 8] Swiftでデザインパターン No.2 Iterator
Iterator design pattern in Swift