Behavioural design patterns help us define manners of communication between classes and objects.
Problem - your program is expected to process different kinds of requests in various ways, but the exact types of requests and their sequences are unknown beforehand. The pattern lets you execute handlers in a particular order.
Solution - you define a chain of receiver objects that have the responsibility, depending on runtime conditions, to either handle the request or forward it to the next receiver in the chain. The request is sent down a chain of receivers withouth knowing which one handles the request.
Problem - you want to create commands that can execute and also undo. For example, you are building a text editor app that has different functionality like bolding the text, changing the font size etc. You have similar looking buttons that do different things.
Solution - the command pattern creates an object that encapsulates all information needed to perform an action or trigger an event at a later time. The command pattern creates a layer of separation between the UI and business logic by creating command classes that have single methods that is triggered by the UI object sending a request to it. The commands become a convenient middle layer that reduces coupling between the UI and business logic layers.
Problem - you need to process user input or convert information from one language into another. The language can be anything such as words in a sentence, numerical formulas or even software code.
Solution - you convert the souce information into an Abstract Syntax Tree (AST) of Terminal or Non-Terminal expressions that all implement an interpret method. A Non-Terminal expression is a combination of other Non-Terminal and or/ Terminal expressions. Terminal means terminated ie no further processing is involved. An AST root starts with a Non-Terminal expression and then resolves down each branch until all expressions terminate.
Problem - you need to access different collections of objects. Objects are usually stored in a list but you can have other more complex data structures.
Solution - you should extract the traversal behaviour of a collection into a separate object called an iterator. An interator object encapsulates all of the traversal details such as the current position and how many elements are left till the end so that several iterators can go through the same collection at the same time, independently of each other. All iterators must implement the same interface to make the client code compatible with any collection type. 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.
Problem - you have tight coupling between a set of interacting objects. Defining a set of interacting objects by accessing and updating each other directly is inflexible and it stops objects from being reusable and makes them hard to test. It should be possible to change the interaction between a set of objects independently.
Solution - the mediator design pattern promotes loose coupling of objects by removing the need for classes to communicate with each other directly. Instead of classes communicating directly, and thus requiring knowledge of their implementation, the classes send messages to a mediator object. The mediator object then transmits the messages to the other classes in a manner that they can interpret.
Problem - you need to restore an object to its previous state
Solution - the internal state of an object is saved externally so that it can be restored to this state later. The memento pattern has three classes - originator, memento and caretake classes. The object (originator) is responsible for saving its internal state to a (memento) object and restoring to a previous state from a (memento) object. A client (caretaker) can request a memento (to save an internal state) from the originator and pass a memento back to the originator (to restore to a previous state)
Problem - you need certain objects to receive an update when another object changes.
Solution - the observer pattern suggests you add a subscription mechanism to the publisher class so that individual objects can subscribe to or unsubscribe from a stream of events coming from that publisher. This mechanism consists of an array list for storing a list of references to subscriber objects and several public methods which allow adding and removing subscribers from that list.
Problem - state is a behavioral design pattern that lets an object alter its behavior when its internal state changes. It appears as if the object changed its class. You use this pattern instead of if/else statements or switch statements to change the state of your class.
Solution - the State Pattern says you create new classes for all the different states of an object. You extract all state specific code into a set of distinct classes. As a result you can add new states of change existing ones independently of eachother, reducing the maintenance cost.
Problem - you have a class that does a specific thing but in a number of different ways.
Solution - you extract all the different algorithms into separate classes called strategies. The original class (context) must have a field for storing a reference to one of the strategies. The context delegates the work to a linked strategy object instead of executing it on its own. It often reduces long lists of conditionals and avoids duplicate code.
Problem - you have two or more classes with significant similarities and you want to reduce duplication.
Solution - to use the template method, you first see which parts of the algorithm are the invariant and which are different. The invariant steps are implemented in an abstract base class while the variant steps are given a default implementation or no implementation at all. The template method is used prominently in frameworks. Each framework implements the invariant pieces of a domain’s architecture, and defines ‘placeholders’ for client customisation options.
Problem - you need to add new behaviour to existing classes without modifying it.
Solution - you place the new behaviour into a separate class called a visitor. The original classes are passed to one of the visitor’s methods as an argument. The visitor will have different methods for each class. In order to know what type of class it has been given and therefore the method to execute it uses a technique called double dispatch. Since the class we are passing as an argument to the visitor class knows what class they are, they can pick a proper method in the visitor class.