• Category: behavioral
  • Type: class
  • Motivation: provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation

diagram

do {
    let list = List()
    list.add(Item(title: "foo"))
    list.add(Item(title: "bar"))
    list.add(Item(title: "baz"))

    var iterator = list.makeIterator()
    while let item = iterator.next()  {
        print(item)
    }
}
protocol Iterator
{
    associatedtype Element
    func next() -> Element?
}

struct ListIterator: Iterator
{
    var index: Int = -1
    var count: Int = 0
    let list: List

    init(_ list: List)
    {
        self.list = list
        self.count = list.count
    }

    typealias Element = Item
    mutating func next() -> Element?
    {
        index += 1
        if index >= count {
            return nil
        }
        return self.list[index]
    }
}
struct Item
{
    let title: String
}

protocol Container
{
    associatedtype Element
    var count: Int { get }
    subscript(_ index: Int) -> Element { get }
    func add(_ element: Element)
    func remove(at index: Int)

    associatedtype Iterator
    func makeIterator() -> Iterator
}

class List: Container {
    var elements: [Item] = []
    typealias Element = Item
    var count: Int { elements.count }
    subscript(_ index: Int) -> Element
    {
        elements[index]
    }

    func add(_ element: Element)
    {
        elements.append(element)
    }

    func remove(at index: Int)
    {
        elements.remove(at: index)
    }
    func makeIterator() -> ListIterator
    {
        ListIterator(self)
    }
}