Greetings, traveler!
The Composite Design Pattern is a Structural Design Pattern. It is a practical tool for composing objects into tree structures. This means you can work with these structures as if they were individual objects, making your code more flexible and easier to manage. It’s like having a tree structure where each element represents a unique object or a collection of objects, all sharing the same interface.
Example of usage
Let’s imagine that we own a fast-food restaurant and have added a new item to our menu — a set of burgers. Our set includes a hamburger, chicken, and veggie burger. These burgers differ in their composition, with different sauces and patties. To prepare each burger, we add a sauce and a patty corresponding to the chosen burger.
protocol BurgerProtocol {
func addPatty()
func addSause()
func pack()
}
extension BurgerProtocol {
func pack() {
print("The \(String(describing: self)) is packed")
}
}
struct Hamburger: BurgerProtocol {
func addPatty() {
print("Beef Patty")
}
func addSause() {
print("Ketchup")
}
}
struct VeggieBurger: BurgerProtocol {
func addPatty() {
print("Vegetable Patty")
}
func addSause() {
print("Mayo")
}
}
struct ChickenBurger: BurgerProtocol {
func addPatty() {
print("Chicken Patty")
}
func addSause() {
print("Mayo + Ketchup")
}
}
By using the Composite design pattern, we can streamline our operations. Instead of dealing with each burger separately, we can create a composite with an identical interface and assign it the responsibility of preparing the entire set. This saves us time and makes our code more efficient and easier to maintain.
final class BurgerSetComposite: BurgerProtocol {
private let setItems: [FastFoodProtocol] = [
Hamburger(),
VeggieBurger(),
ChickenBurger()
]
func addPatty() {
setItems.forEach {
$0.addPatty()
}
}
func addSause() {
setItems.forEach {
$0.addSause()
}
}
func pack() {
setItems.forEach {
$0.pack()
}
}
}
let composite = BurgerSetComposite()
composite.addPatty()
composite.addSause()
composite.pack()
Looks good!
Conclusion
The Composite Design Pattern is widely used due to its simplicity. It helps us to create a unified interface for working with multiple components, making it easier to manage and maintain. I hope you found this article helpful. In the following article, we will discuss the Decorator Design Pattern. See you there!
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
- Decorator 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