• Category: behavioral
  • Type: object
  • Motivation: add new visitor without change existed visitor and element (driver -> print)

diagram

do {
    let car = Car()
    car.accept(Driver())
    car.accept(Printer())

    let engine = Engine()
    engine.accept(Printer())
}
protocol Visitor
{
    func visit(engine: Engine)
    func visit(body: Body)
    func visit(wheel: Wheel)
    func visit(car: Car)
}

extension Visitor {
    func visit(car: Car)
    {

    }
}

class Driver: Visitor
{
    func visit(engine: Engine)
    {
        print("start engine")
    }

    func visit(body: Body)
    {
        print("move body")
    }

    func visit(wheel: Wheel)
    {
        print("kick wheel")
    }
}

class Printer: Visitor
{
    func visit(engine: Engine)
    {
        print("print engine")
    }

    func visit(body: Body)
    {
        print("print body")
    }

    func visit(wheel: Wheel)
    {
        print("print wheel")
    }
}
protocol Element
{
    func accept(_ visitor: Visitor)
}

class Engine: Element
{
    func accept(_ visitor: Visitor)
    {
        visitor.visit(engine: self)

    }
}

class Body: Element
{
    func accept(_ visitor: Visitor)
    {
        visitor.visit(body: self)
    }
}

class Wheel: Element
{
    func accept(_ visitor: Visitor)
    {
        visitor.visit(wheel: self)
    }
}

class Car: Element
{
    private var elements: [Element] = []

    init()
    {
        self.elements = [
            Engine(),
            Wheel(),
            Body(),
        ]
    }

    func accept(_ visitor: Visitor)
    {
        for elt in elements {
            elt.accept(visitor)
        }
        visitor.visit(car: self)
    }
}