7/180: Behavioral Design Patterns

Navneet Ojha
6 min readMar 25, 2021

Today is day 7 of 180 days challenge. The purpose of taking this challenge is to develop a habit of learning.

Today we are going to discuss about Behavioral Design Patterns. These patterns basically identify communication between objects. By doing this it increase the flexibility in carrying out communication.

Types of Behavioral Design Patterns:

  1. Chain of Responsibility
  2. Command
  3. Interpreter
  4. Iterator
  5. Mediator
  6. Memento
  7. Null Object
  8. Observer
  9. State
  10. Strategy
  11. Template Method
  12. Visitor

All the above are different types of Behavioral design patterns. And we are going to discuss in brief about all.

Chain of Responsibility

Sequence of handlers processing an event one after another.

Need of this pattern: Unethical behavior of the employee who takes the blame? Employee -> manager -> CEO

A chain of components who all get a chance to process a command or query, optionally having default processing implementation and an ability to terminate the processing chain.

Command

You shall not pass

Need of this pattern: Ordinary java statements are perishable. Cannot undo a field assignment. Cannot directly serialize sequence of actions(calls). Want an object that represent operation. X should change it’s field y to value z. X should do W(). Use GUI commands, multilevel undo/redo, macro recording and more.

An object which represents an instruction to perform particular action. Contain all the information necessary for the action to be taken.

Encapsulate all details of an operation in separate object. Define instructions for applying the command. optional defines instructions for undoing the command. Can create composite commands.

Interpreter

Interpreters are all around us. Even now in this very room.

Need of this pattern: Textual inputs needs to be processed example turned into OOPs structure. Some examples: Programming language compilers, interpreters and ide’s. Turning string into OOPs based structure in a complicated process.

A component that process structured text data. Does so by turning it into special lexical tokens and then interpreting sequence of said tokens

Iterator

How traversal of data structures happens and who make it happen.

Need of this pattern: Iteration is a core functionality of various data structures. An iterator is a class that facilitates the traversal. Keeps a reference to the current element. Knows how to move to a different element. Java has Iterator<T> and Iterable<T>. Iterator<T > specifies the iterator API. A class needs to be iterable to support for(Foo foo : bar) loops.

Its an object that facilitates the traversal of data structures.

An iterator specifies how you can traverse an object. Iterator cannot be recursive. Iterator implements Iterator<T>. Iterable object implements Iterable<T>

Mediator

Create the mediator and have each object in the system refer to it. example in field. Mediator engages in bidirectional communication with its connected components. Mediator has functions the components can call. Components have functions mediator can call. Event processing libraries make communication easier to implement.

Memento

Keep a memento of an objects state to return to that state.

Need of this pattern: An object or system goes through changes. there are different ways of navigating those changes. One way is to record every change (command) and teach a command to undo itself. Another is to simply save the snapshot of the system.

A token/handle representing the system state. Let us roll back to the state when the token was generated. May or may not directly expose state info.

Memento’s are used to rollback states arbitrarily. A memento is simply a token/handle class with(typically) no functions of its own. A memento is not required to expose directly the state(s) to which it reverts the system. Can be used to implement undo/redo.

Null Object

A behavioral design pattern with no behaviors

Need for this pattern: When component A uses component B, it typically assumes that B is non null value. You inject B, not some option B type. You do not check for null on every call. there is not option of telling A not to use an instance of B. It use is hard coded. Thus we a no-op, non-functioning inheritor of B and pass it into A.

A no-op object that conforms to the required interface satisfying a dependency requirement of sum object.

Implement the required interface. Rewrite the methods with empty bodies. If method is non-void, return default value for given type. If these values are ever used you are in trouble. Supply an instance of null object in place of actual object

Observer

I am watching you

Need of this pattern: We need to be informed when certain things happen. Object’s field changes, object does something, some external event occurs.

We want to listen to events and notified when they occur. Typical pattern involves addXListner(), java now has functional objects Supplier<T>, Consumer<T>, Function<T>.

An observer is an object that wishes to be informed about events happening in the system. The entity generating the events is an observable.

Observer is an intrusive approach: an observable must provide an event to subscribe to. Special care must be taken to prevent issues in multithreading scenarios.

State

Fun with finite state machines

Need of this pattern: Consider an ordinary telephone. What you do with it depends upon the state of the phone/line. If it’s ringing or you want to make a call, you can pick it up. Phone must be off the hook to talk/make a call. If you trying calling someone, and it’s busy, you put the handset down. Changes in state can be explicit or in response to event (Observer pattern)

A pattern in which objects behavior is determined by it’s state. An object transitions from one state to another (something needs to trigger a transition). A formalized construct which manages state and transitions is called a state machine.

Given sufficient complexity, it pays to formally define possible states and events/triggers.

Can define-> state entry exit behavior, Action when particular event causes transition, Guard conditions enabling/ disabling a transition, default action when no transition are found for an event.

Strategy

System behavior partially specified at runtime

Need of this pattern: Many algorithms can be decomposed into higher and lower level parts. Like making tea can be decomposed into the process of making a hot beverage (boil water, pour into cup) and tea specific things (put tea bag into water). The high level algorithm can then be reused for making coffee or hot chocolate. Supported by beverage specific strategies.

It enables the exact behavior of a system to be selected either at run time (dynamic) or compile time (static). It is also known as policy.

Define an algorithm at a high level. Define the interface you expect each strategy to follow. Provide for either dynamic or static composition of strategy in the overall algorithm.

Template Method

A high level blue print for an algorithm to be completed by inheritors

Need of this pattern: Algorithm can be decomposed into common parts + specifics. Strategy pattern does this through composition: High level algorithm uses an interface. Concrete implementations implement the interface. Templated method does same things through inheritance. Overall algorithm makes use of abstract members. inheritors override the abstract members parent template method invoked.

This pattern allows us to define the skeleton of the algorithm with concrete implementations defined in subclasses.

Visitor

Allows adding extra behavior to entire hierarchies of classes.

Need of this pattern: Need to define new operation on entire class hierarchy. example: make a document model printable to HTML/Markdown. Don't want to keep modifying every class in hierarchy. Need access to non common aspects of classes in hierarchy. Create an external component to handle rendering. But avoid type checks

A pattern where component(visitor) is allowed to traverse the entire inheritance hierarchy. Implemented by propagating single visit() method throughout entire hierarchy.

Propagating an accept (Visitor v) method through out entire hierarchy. Create a visitor with visit(foo) visit(bar) for each element in hierarchy. Each accept() simply calls visitor.visit(this). Acyclic visitor allows greater flexibility at a cost of performance.

--

--

Navneet Ojha

I am Indian by birth, Punjabi by destiny. Humanity is my religion. Love to eat, travel, read books and my million dreams keep me alive.