[ad_1]
Discover ways to implement the builder sample in Swift to cover the complexity of making objects with a number of particular person properties.
Design patterns
How does the builder sample work?
The builder sample might be applied in a number of methods, however that actually does not issues in the event you perceive the primary aim of the sample:
The intent of the Builder design sample is to separate the development of a fancy object from its illustration.
So when you have an object with a number of properties, you need to conceal the complexity of the initialization course of, you could possibly write a builder and assemble the article by way of that. It may be so simple as a construct technique or an exterior class that controls the complete building course of. All of it will depend on the given atmosphere. 🏗
That is sufficient concept for now, let’s examine the builder sample in motion utilizing dummy, however real-world examples and the highly effective Swift programming language! 💪
Easy emitter builder
I consider that SKEmitterNode is sort of a pleasant instance. If you wish to create customized emitters and set properties programmatically – normally for a SpriteKit recreation – an emitter builder class like this might be an affordable resolution. 👾
class EmitterBuilder {
func construct() -> SKEmitterNode {
let emitter = SKEmitterNode()
emitter.particleTexture = SKTexture(imageNamed: "MyTexture")
emitter.particleBirthRate = 100
emitter.particleLifetime = 60
emitter.particlePositionRange = CGVector(dx: 100, dy: 100)
emitter.particleSpeed = 10
emitter.particleColor = .crimson
emitter.particleColorBlendFactor = 1
return emitter
}
}
EmitterBuilder().construct()
Easy theme builder
Let’s transfer away from gaming and picture that you’re making a theme engine in your UIKit software which has many customized fonts, colours, and so forth. a builder might be helpful to assemble standalone themes. 🔨
struct Theme {
let textColor: UIColor?
let backgroundColor: UIColor?
}
class ThemeBuilder {
enum Model {
case gentle
case darkish
}
func construct(_ fashion: Model) -> Theme {
swap fashion {
case .gentle:
return Theme(textColor: .black, backgroundColor: .white)
case .darkish:
return Theme(textColor: .white, backgroundColor: .black)
}
}
}
let builder = ThemeBuilder()
let gentle = builder.construct(.gentle)
let darkish = builder.construct(.darkish)
“Chained” URL builder
With this strategy you’ll be able to configure your object by way of numerous strategies and each single one in all them will return the identical builder object. This fashion you’ll be able to chain the configuration and as a final step construct the ultimate product. ⛓
class URLBuilder {
non-public var parts: URLComponents
init() {
self.parts = URLComponents()
}
func set(scheme: String) -> URLBuilder {
self.parts.scheme = scheme
return self
}
func set(host: String) -> URLBuilder {
self.parts.host = host
return self
}
func set(port: Int) -> URLBuilder {
self.parts.port = port
return self
}
func set(path: String) -> URLBuilder {
var path = path
if !path.hasPrefix("https://theswiftdev.com/") {
path = "https://theswiftdev.com/" + path
}
self.parts.path = path
return self
}
func addQueryItem(title: String, worth: String) -> URLBuilder {
if self.parts.queryItems == nil {
self.parts.queryItems = []
}
self.parts.queryItems?.append(URLQueryItem(title: title, worth: worth))
return self
}
func construct() -> URL? {
return self.parts.url
}
}
let url = URLBuilder()
.set(scheme: "https")
.set(host: "localhost")
.set(path: "api/v1")
.addQueryItem(title: "type", worth: "title")
.addQueryItem(title: "order", worth: "asc")
.construct()
The builder sample with a director
Let’s meet the director object. Because it looks like this little factor decouples the builder from the precise configuration half. So for example you can also make a recreation with circles, however in a while in the event you change your thoughts and you would like to make use of squares, that is comparatively straightforward. You simply need to create a brand new builder, and the whole lot else might be the identical. 🎬
protocol NodeBuilder {
var title: String { get set }
var colour: SKColor { get set }
var dimension: CGFloat { get set }
func construct() -> SKShapeNode
}
protocol NodeDirector {
var builder: NodeBuilder { get set }
func construct() -> SKShapeNode
}
class CircleNodeBuilder: NodeBuilder {
var title: String = ""
var colour: SKColor = .clear
var dimension: CGFloat = 0
func construct() -> SKShapeNode {
let node = SKShapeNode(circleOfRadius: self.dimension)
node.title = self.title
node.fillColor = self.colour
return node
}
}
class PlayerNodeDirector: NodeDirector {
var builder: NodeBuilder
init(builder: NodeBuilder) {
self.builder = builder
}
func construct() -> SKShapeNode {
self.builder.title = "Whats up"
self.builder.dimension = 32
self.builder.colour = .crimson
return self.builder.construct()
}
}
let builder = CircleNodeBuilder()
let director = PlayerNodeDirector(builder: builder)
let participant = director.construct()
Block primarily based builders
A extra swifty strategy might be using blocks as a substitute of builder lessons to configure objects. After all we might argue on if that is nonetheless a builder sample or not… 😛
extension UILabel {
static func construct(block: ((UILabel) -> Void)) -> UILabel {
let label = UILabel(body: .zero)
block(label)
return label
}
}
let label = UILabel.construct { label in
label.translatesAutoresizingMaskIntoConstraints = false
label.textual content = "Whats up wold!"
label.font = UIFont.systemFont(ofSize: 12)
}
Please observe that the builder implementation can range on the particular use case. Generally a builder is mixed with factories. So far as I can see virtually everybody interpreted it otherwise, however I do not suppose that is an issue. Design patterns are well-made tips, however typically you must cross the road.
[ad_2]
