
Objects need to collaborate to accomplish tasks. Behavioral patterns define clear communication protocols, making interactions flexible and maintainable.
Lets you traverse elements of a collection without exposing its underlying representation (list, stack, tree, etc.).
A collection is just a container for a group of objects. Most common collections are based on lists lists, but often they are based on stacks, trees, graphs and other complex data structures. But no matter how a collection is structured, it must provide some way of to go through each element of the collection. It’s an easy job if the collection is based on a list (loop over all the elements); but for example it is not on a tree (you might need depth-first traversal once, then breadth-first traversal another time, etc.).
Adding more and more traversal algorithms to the collection gradually blurs its primary responsibility, which is efficient data storage. Additionally, some algorithms might be tailored for a specific application, so including them into a generic collection class would be weird. On the other hand, the client code that’s supposed to work with various collections may not even care how they store their elements. However, since collections all provide different ways of accessing their elements, you have no option other than to couple your code to the specific collection classes.
The main idea of the Iterator pattern is to extract the traversal behavior of a collection into a separate object called an iterator.
In addition to implementing the algorithm itself, an iterator object encapsulates all of the traversal details, such as the current position and how many elements are left till the end. Because of this, several iterators can go through the same collection at the same time, independently of each other.
Usually, iterators provide one primary method for fetching elements of the collection. The client can keep running this method until it doesn’t return anything, which means that the iterator has traversed all of the elements.
All iterators must implement the same interface. This makes the client code compatible with any collection type or any traversal algorithm as long as there’s a proper iterator. If you need a special way to traverse a collection, you just create a new iterator class, without having to change the collection or the client.
Example:

This way, the iterator pattern lets you traverse different data structure, even if some of them are unknown beforehand; also complexity is hidden from the client.

Defines the skeleton of an algorithm in the superclass but lets subclasses override specific steps of the algorithm without changing its structure.
aaa
aaa
aaa
aaa
Lets you pass requests along a chain of handlers. Upon receiving a request, each handler decides either to process the request or to pass it to the next handler in the chain.
aaa
aaa
aaa
aaa
Turns a request into a stand-alone object that contains all information about the request. This transformation lets you pass requests as a method arguments, delay or queue a request’s execution, and support undoable operations.
aaa
aaa
aaa
aaa
Lets you save and restore the previous state of an object without revealing the details of its implementation.
aaa
aaa
aaa
aaa
aaa
Lets you define a subscription mechanism to notify multiple objects about any events that happen to the object they’re observing.
Imagine a customer eagerly awaiting a new iPhone at a store. They could check the store daily, often in vain, or the store could send frequent notifications to all customers, annoying those not interested. This creates a conflict: either the customer wastes time checking, or the store wastes resources and risks spamming uninterested customers.
The object that has some interesting state is called publisher; all other objects that want to track changes to the publisher’s state are called subscribers. This pattern suggests adding a subscription mechanism to the publisher class, so individual objects can subscribe to or unsubscribe from a stream of events coming from that publisher.
Whenever an event happens to the publisher, it goes over its subscribers and calls the specific notification method on their objects. Publisher doesn’t need to know much about subscribers different classes: so it’s crucial that they implement the same interface (with notification method and a set of parameters), and that the publisher communicates with them only via that interface.
If you have multiple publisher, even them can implement same interface, so that subscribers can observe them with same methods.

Use the Observer pattern when:
| Pros | Cons |
|---|---|
| Open/Closed Principle. You can introduce new subscriber classes without having to change the publisher’s code (and vice versa if there’s a publisher interface) | Subscribers are notified in random order |
| You can establish relations between objects at runtime |
Lets you define a family of algorithms, put each of them into a separate class, and make their objects interchangeable.
aaa
aaa
aaa
aaa
Lets you reduce chaotic dependencies between objects. The pattern restricts direct communications between the objects and forces them to collaborate only via a mediator object.
aaa
aaa
aaa
aaa
Lets an object alter its behavior when its internal state changes. It appears as if the object changed its class.
aaa
aaa
aaa
aaa
Lets you separate algorithms from the objects on which they operate.
aaa
aaa
aaa
aaa
Images sources: https://refactoring.guru/design-patterns/