Let us discuss how Prototype design pattern in this article:
It’s a creational pattern that is used when creating an object of a class is either expensive or complex.
Let’s say you have an object and you want to create copy of it. To create copy, you need know all requirements and there are chances some private properties are not available to you.
How can objects be created so that which objects to create can be specified at run-time?
Implementing clone() can be difficult when their internals include objects that don’t support copying or have circular references.
Change the initializer for the class or struct used for the prototype object and check whether a corresponding change is required in the component that creates clones.
This pattern is often used with factory, composition or decorator patterns.
The Prototype pattern delegates the cloning process to the actual objects that are being cloned. The pattern declares a common interface for all objects that support cloning. This interface lets you clone an object without coupling your code to the class of that object.
An object that supports cloning is called a prototype. When your objects have dozens of fields and hundreds of possible configurations, cloning them might serve as an alternative to subclassing.
Swift automatically applies the prototype pattern when you assign a value type to a new variable. Values types are defined using structs, and all of the built-in Swift types are implemented as structs behind the scenes, meaning that you can clone strings, Booleans, collections, enumerations, tuples, and numeric types just by assigning them to a new variable. Swift will copy the value of the prototype and use it to create a clone. struct having reference types are shallow copied, they are deep copied only on modification.
import Foundation
protocol Cloneable {
func copy() -> Any
}
class Message: Cloneable {
var to: String
var subject: String
init(to: String, subject: String) {
self.to = to
self.subject = subject
}
func copy() -> Any {
return Message(to: to, subject: subject)
}
}
class DetailedMessage: Message {
var from: String
init(to: String, subject: String, from:String) {
self.from = from
super.init(to: to, subject: subject)
}
override func copy() -> Any {
return DetailedMessage(to: to, subject: subject, from: from)
}
}
class MessageLogger {
var messages:[Message] = []
func logMessage(_ msg: Message) {
guard let messageCopy = msg.copy() as? Message else { return }
messages.append(messageCopy)
}
func processMessages(_ callback: (Message) -> Void) {
for msg in messages {
callback(msg)
}
}
}
var logger = MessageLogger()
var message = Message(to: "Joe", subject: "Hello")
logger.logMessage(message)
message.to = "Bob"
message.subject = "Free for dinner?"
logger.logMessage(message)
logger.logMessage(DetailedMessage(to: "Alice", subject: "Hi!", from: "Joe"))
logger.processMessages({msg -> Void in
if let detailed = msg as? DetailedMessage {
print("Detailed Message - To: \(detailed.to) From: \(detailed.from)" + " Subject: \(detailed.subject)")
} else {
print("Message - To: \(msg.to) Subject: \(msg.subject)")
}
})
In this example, I created aCloneable protocol, all prototypes need to conform to this protocol. There is another way to implement copy is by conforming to NSCopying protocol and for that class should conform to NSObject.
This is a free third party commenting service we are using for you, which needs you to sign in to post a comment, but the good bit is you can stay anonymous while commenting.