Difficulty: Beginner | Easy | Normal | Challenging
This article has been developed using Xcode 11.5, and Swift 5.2.4
This is a rather uncommon design pattern, but is one worth studying in any case. The idea here is to separate out the algorithm from the objects that that algorithm operates on,
- You will be expected to be aware how to make a Single View Application in Swift.
Design Pattern: a general, reusable solution to a commonly occurring problem
Take the following example:
protocol Animal {
func makeSound()
}
class Dog: Animal {
func makeSound() {
print ("Woof")
}
}
class Cat: Animal {
func makeSound() {
print ("Meow")
}
}Now if we wish to add a new operation to our animals (something like a func move()) we must modify the interface to every single class in the hierarchy: the result could be something like the following
protocol Animal {
func makeSound()
func move()
}
class Dog: Animal {
func makeSound() {
print ("Woof")
}
func move() {
print ("Run")
}
}
class Cat: Animal {
func makeSound() {
print ("Meow")
}
func move() {
print ("Jump")
}
}of course I've not implemented move, but still - you should get the idea of this.
Take the following example:
protocol Animal {
func accept(_ visitor: Visitor)
}
// concrete component A
class Dog: Animal {
func accept(_ visitor: Visitor) {
visitor.hereIsADog(d: self)
}
}
// concrete component B
class Cat: Animal {
func accept(_ visitor: Visitor) {
visitor.hereIsACat(c: self)
}
}
// abstract Visitor class (Operation)
protocol Visitor {
func hereIsADog(d: Dog)
func hereIsACat(c: Cat)
}
class Sound: Visitor {
func hereIsADog(d: Dog) {
print ("Woof")
}
func hereIsACat(c: Cat) {
print ("Miow")
}
}
let animals: [Animal] = [Cat()]
let visitor1 = Sound()
let _ = animals.map{ animal in
let theSound = Sound()
animal.accept(theSound)
}Which gives the result (as there is just a cat in the example) of
MiowNow to implement something like Move we can create a new class called Move
class Move: Visitor {
func hereIsADog(d: Dog) {
print ("Run")
}
func hereIsACat(c: Cat) {
print ("Jump")
}
}which would then require us to create map the movement in a similar style to the above:
let _ = animals.map{ animal in
let theMovement = Move()
animal.accept(theMovement)
}Giving the result as
Miow
JumpThere are other advantages, in that you can have collections of mismanaged objects and can perform operations on them.
If you've any questions, comments or suggestions please hit me up on Twitter
