Understanding Behavioral Design Patterns
A few key examples
Welcome back to our design patterns series. In the first part of this series, we discussed six structural design patterns. In this second installment, we will be looking at behavioral patterns. Behavioral patterns allow our objects to communicate with each other, whether it be one-to-one or many-to-one.
The Delegation Pattern
I remember when I first heard of a delegate, introduced to me as a way of allowing objects to communicate with one another. The initial obstacle I had when working with delegates was creating a distinction between delegates and protocols.
A protocol is a set of requirements that every type which conforms to it is expected to implement. A protocol contains declaration detail, not implementation details. Delegates are implemented using protocols and are useful because they establish a one-to-one method of communication between objects. (It should be noted that in situations where a single closure can be used to communicate changes to an object, delegates may be overkill.)
The Observer Pattern
Unlike delegation, this pattern allows our objects to communicate in a one-to-many relationship. Here are some of the observers used in iOS:
According to Apple, this native API is a mechanism that enables the broadcasting of information to registered observers. You should consider using this API if you have multiple objects that need to listen for the same change, without those objects having a direct connection to each other. It’s also useful if that change has to be observed repeatedly.
There are a few downsides to using this pattern—for one, it is not very easy to track bugs. Unlike delegation, notifications and their observers have an indirect relationship. This can make it harder to track down where a notification is coming from or where it’s being observed. Additionally, the object that sent the notification and the objects that listen for the changes must know about the notification
userInfo. Further, there is no deterministic order to how objects listening to changes receive these notifications.
With key-value observers, one type can observe the properties of another type to find out about changes to the observed type’s state. These kinds of observers can provide an easy way for information to be synced between objects, and can provide an easy way for us to obtain a new value and the previous value of a property.
This is by no means a complete list of behavioral patterns, but it’s a good place to get started. In the third and final installment of this series, coming soon, we’ll take a look at creational patterns.