読者です 読者をやめる 読者になる 読者になる

swiftでデザインパターンを実装(Iteratorパターン)

今回はIteratorパターンを実装します

  • Iteratorパターンとは?

  • 登場人物

    • Iterator
      • 走査、データの取り出しを行うためのインタフェース
    • ConcreateIterator
      • Iteratorインタフェースを実装するクラス
    • Aggregate
      • 集合を管理し、Iteratorオブジェクトを生成するためのインタフェース
    • ConcreateAggregate
      • Aggregateインタフェースを実装するクラス
    • Element
      • ConcreateAggregateで管理される要素クラス

参考: (株)オージス総研「事例で学ぶデザインパターン 第2回 Iteratorパターンの適用例を見て学ぼう」

参考: developers.IO 「[iOS 8] Swiftでデザインパターン No.2 Iterator」

Element

class Song {
    private var name: String
    
    init (name: String) {
        self.name = name
    }
}

Aggreate

class Aggregate {
    func iterator() -> Iterator {
        fatalError("サブクラスで使ってね")
    }
}

Iterator

class Iterator {
    func next() -> AnyObject {
        fatalError("サブクラスで使ってね")
    }
    
    func hasNext() -> Bool{
        fatalError("サブクラスで使ってね")
    }
}

ConcreateIterator

class SongIterator: Iterator {
    private var songAggregate: SongAggregate
    private var index = 0
    
    init(songAgregate: SongAggregate) {
        self.songAggregate = songAgregate
    }
    
    override func next() -> AnyObject {
        return songAggregate.songAtIndex(index++)
    }
    
    override func hasNext() -> Bool {
        return songAggregate.countOfSongs() > index
    }
    
}

ConcreateAggregate

class SongAggregate: Aggregate {
    private var songs = [Song]()
    
    override func iterator() -> Iterator {
        return SongIterator(songAgregate: self)
    }
    
    func addSong(song: Song) {
        songs.append(song)
    }
    
    func countOfSongs() -> Int {
        return songs.count
    }
    
    func songAtIndex(index: Int) -> Song {
        return songs[index]
    }
}

使い方

var songAggregate = SongAggregate()

songAggregate.addSong(Song(name: "POP MASTER"))
songAggregate.addSong(Song(name: "ETERNAL BLAZE"))
songAggregate.addSong(Song(name: "DISCOTIQUE"))

let songIterator = songAggregate.iterator()


while songIterator.hasNext() {
    let song = songIterator.next() as! Song
    print(song.name)
}

swift固有の書き方

  • SequenceTypeとGeneratorTypeを用いた実装方法があるみたいなので今度実装してみたいと思います。

参考: kanetaiの二次記憶装置

感想

Iteratorを挟むことによって、Controller側がElement(Model)のことを気にせずにアクセスできています。 Modelに変更があった場合、Contorollerへの影響が少なくて済むのではないでしょうか Iteratorパターンが使われているOSSも探してみたいと思います。