今回参考にさせていただいた書籍です
増補改訂版Java言語で学ぶデザインパターン入門
protocolの実装
protocol Iterator {
associatedtype Item
var hasNext: Bool { get }
func next()->Item
}
iteratorはaggregateから生成されて、配列を数え上げるprotocolです。
protocol Aggregate {
associatedtype IteratorImpl: Iterator
var iterator: IteratorImpl { get }
}
aggregateは対応したiteratorを返します。
実装クラスの実装
class Book {
let name: String
init(name: String) {
self.name = name
}
}
数え上げられるItemです。
class BookShelf: Aggregate {
typealias IteratorImpl = BookShelfIterator
var len: Int {
return books.count
}
private(set) var books: [Book] = []
var iterator: BookShelfIterator {
return BookShelfIterator(self)
}
func appendBook(book: Book) {
self.books.append(book)
}
}
Aggregateの実装クラスです。
書籍の方では取得するために、getBookAt(index:Int)で本を取得してましたが、private(set) varで十分だと思い今回は実装していません。
class BookShelfIterator: Iterator {
typealias Item = Book
private let shelf: BookShelf
private var index: Int
var hasNext: Bool {
if index < shelf.len {
return true
} else {
return false
}
}
init(_ shelf: BookShelf) {
self.shelf = shelf
self.index = 0
}
func next() -> Book {
defer {
self.index += 1
}
return self.shelf.books[self.index]
}
}
BookShelfIteratorは書籍の方と同じです。
呼び出し
var shelf = BookShelf()
shelf.appendBook(book: Book(name: "Code Complete"))
shelf.appendBook(book: Book(name: "Design Pattern"))
shelf.appendBook(book: Book(name: "Clean Architecture"))
var iterator = shelf.iterator
while (iterator.hasNext) {
print(iterator.next().name)
}
呼び出しに関してはほぼ書籍通りになってますが、個人的にiteratorから帰ってくる値がAnyもしくはAnyObjectが嫌だったので、associatedtype
を使って実装クラスで返す値の型とiteratorの型を決定しています。
なのでmain.swift
に書かれてるiteratorはiteratorに準拠したクラスになるため、iteratorのhasNext
、next()
を呼んでいるというより、iteratorに準拠したhasNext
、next()
を呼んでいることになります。
勉強がてらデザインパターンをSwiftで書き起こしをしてみましたが、いろいろ勉強になることがあったので、他のパターンでもやってみようと思います。改善点などがあれば教えていただけると助かります。