Greetings, traveler!
We continue researching Structural Design Patterns as part of our Design Patterns course. It’s the turn of the Decorator Design Pattern. We can use this pattern to modify an object’s behavior without inheritance. A decorator is a wrapper that alters an object’s behavior to provide the desired result in a specific situation. The decorator has a similar interface to the object it wraps, which means it can be used as a wrapper for other decorators. However, it’s important not to overdo it with decorators, as this can make the code more complicated and challenging to understand.
Example of usage
Let’s take a look at an example. As before, I’d like to give an example from the fast-food world. Imagine we have a restaurant where we serve burgers to our customers. At the same time, we offer the option of adding cheese to a cheeseburger. Naturally, the price of a cheeseburger would increase if we added more cheese. Additionally, it would be helpful to change the description so that our customers know we haven’t forgotten about their small request.
Let’s create a special protocol and our cheeseburger model.
protocol CheeseburgerProtocol {
var name: String { get }
var price: Double { get }
}
struct Cheeseburger: CheeseburgerProtocol {
let name: String = "Cheeseburger"
let price: Double = 5.00
}
And now, let’s create a Decorator that will allow us to add extra cheese to the cheeseburger, automatically adjusting its price and description accordingly.
struct CheeseburgerDecorator: CheeseburgerProtocol {
var name: String {
let extraCheeseString = extraCheese == .zero ? "" : " with extra cheese"
return burger.name + extraCheeseString
}
var price: Double {
burger.price + (Double(extraCheese) * 0.30)
}
private let burger: CheeseburgerProtocol
private let extraCheese: Int
init(
burger: CheeseburgerProtocol,
extraCheese: Int
) {
self.burger = burger
self.extraCheese = extraCheese
}
}
let cheeseburger = Cheeseburger()
let decorator = CheeseburgerDecorator(burger: cheeseburger, extraCheese: 3)
Excellent!
Conclusion
The decorator is a useful tool but should be used carefully and with knowledge to avoid creating overly complex code.
Alight then! Now that we have finished with the Decorator, we can move on to the next Design Pattern, the Facade. See you in the following article.
Check out other posts in the Design Patterns series:
- Visitor Design Pattern in Swift
- Themplate Method Design Pattern in Swift
- Strategy Design Pattern in Swift
- State Design Pattern in Swift
- Observer Design Pattern in Swift
- Memento Design Pattern in Swift
- Mediator Design Pattern in Swift
- Iterator Design Pattern in Swift
- Command Design Pattern in Swift
- Chain of Responsibility Design Pattern in Swift
- Proxy Design Pattern in Swift
- FlyWeight Design Pattern in Swift
- Facade Design Pattern in Swift
- Composite Design Pattern in Swift
- Bridge Design Pattern in Swift
- Adapter Design Pattern in Swift
- Singleton Design Pattern in Swift
- Prototype Design Pattern in Swift
- Builder Design Pattern in Swift
- Abstract Factory Design Pattern in Swift
- Factory Method Design Pattern in Swift
- Design Patterns: Basics