← All Notes programming

Behavorial Design Patterns

Describe basics of most behavorial design patterns.

#design-patterns#behavorial

Table of contents

  1. Chain Of Responsibility Pattern
  2. Command Pattern
  3. Memento Pattern
  4. Observer Pattern
  5. State Pattern
  6. Strategy Pattern
  7. Template Pattern
  8. Sources

Chain Of Responsibility Pattern

Introduction

Behavorial design pattern that lets you pass request 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.

Example

You are contracted by a company that want to add filter and process specific actions for each mail they receive. They already made an AI that group those mails by types but want you to find an efficient to process those and to add new mail groups. You then choose to implement a Chain Of Responsibility design pattern where mails will pass through the spam filter, then support, sponsoring, etc.

Implementation

  • An Handler interface that declares the common behavior between for all concrete handlers. Can contains a method for setting the next handler in the chain.
  • An optional BaseHandler class that can contain the boilerplate code common to all handler classes.
  • Concrete handlers which contains the actual code for processing requests. Upon receiving a request, they must decide whether to process the it and, additionally, whether to pass it along the chain.
  • The Client that compose chains just once or dynamically.

Note: request can be sent to any handlers in the change, not necessarily the first in the chain.

Diagram

Chain Of Responsibility Design Pattern Diagram

Use case

  • When 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.
  • When it’s essential to execute several handlers in a particular order.
  • When the set of handlers and their order are supposed to change at runtime

Command Pattern

Introduction

Behavorial design pattern that turns a request into a stand-alone object that contains all information about the request. This transformation lets you pass request as a method arguments, delay or queue a request’s execution, and support undoable operations.

Example

You are building a text editor and you just implemented a toolbar with a copy and paste button. You later add a menu displayed on a click that also happen to show a copy and paste option. And even later, you add support for the Ctrl+C shortcut. You realise that you have 3 classes (CopyButton, CopyMenuItem, CopyShortcut) that each send its own yet equal request to the business logic. You want to centralize it so that it’s easier to maintain and update if needed.

Implementation

  • A Sender/ Invoker class responsible for initiating requests. Must have a field storing a reference to a command object. Triggers that command instead of sending the request directly to the receiver.
  • A Command interface that usually declares just a single method for executing the command.
  • Concrete commands that implements various kinds of requests. Not supposed to perform the work but rather to pass the call to one of the business logic objects. But for code simplications, they can be merged.
  • The Receiver class contains some businness logic. Any object could act as a receiver. Most commands only handle the details of how a request is passed to the receiver, while the receiver itself actually does the work.
  • The Client creates and configures commands objects. The client must pass all of the request parameter, including a receiver instance, into the command’s constructor.

Diagram

Command Design Pattern Diagram

Use case

  • When you want to parameterize objects with operations.
  • When you want to queue operators, schedule their execution, or execute them remotely.
  • When you want to implement reversible operations.

Memento Pattern

Introduction

Behavorial design pattern that lets you save and restore the previous state of an object without revealing the details of its implementation.

Example

You are coding your own IDE and start implementing the undo/redo functions. At first, you want to create a copy of the current instance and store it, and on redo, replace all the fields with the previously stored values. You also start thinking about a way to store those states and you figure that you could store them in a list. By continuing your to think about you see that you reached a dead-end, either you expose all internal details of classes (too fragile) or restrict acces to their state (impossible to produce snapshots). One way to solve this is the Memento design pattern.

Implementation

  • An Originator class that can produce snaphsots of its own state, as well as restore its state from snaphots when needed.
  • A Memento value object that acts as a snapshot of the Originator’s state. It’s a common practice to make it immutable and pass it the data once, via the constructor.
  • A Caretaker that knows “when” and “why” to capture the Originator’s state, but also when it should be restored.
  • In the following diagram implementation, the Memento class is nested inside the Originator to let it access fields and methods of the Memento. And Caretaker has very limited access to Memento’s fields which lets it stores in a stack but not tamper with their state.

Diagram

Nested classes

Nested Class Memento Design Pattern Diagram

Intermediate interface

Intermediate Interface Memento Design Pattern Diagram

Stricter encapsulation

Stricter Encapsulation Memento Design Pattern Diagram

Use case

  • When you want to produce snapshots of the object’s state to be able to restore to a previous state of the object.
  • When direct access to the object fields/getters/setters violates its encapsulation.

Observer Pattern

Introduction

Behavorial design pattern that lets you define a subscription mechanism to notify multiple objects about any events that happen to the object they’re observing.

Example

You are making a family calendar app. You want to track for new events and your first thoughts are to send check if something new happened every seconds. Seeing it’s not a good idea you try thinking from the calendar server that would send updates over network every time something new happen. But you realise that you may not want to flood the network with some random information that nobody or only few people would like to receive. It would be fine to be able to store only those who wants to receive updates, there comes the Observer design pattern.

Implementation

  • A Publisher that issues events to other objects. These events occur when the publisher changes its state or executes some behavior. They contains a subscription infrastructure that lets new subscribers join and leave the list.
  • On a new event, every subscriber in the list are notified via the notification method declared in the Subscriber interface.
  • The Subscriber interface declares the notification interface. It often consists of a single update method.
  • Concrete subscribers that performs some actions in response to notifications by the publishers. They must all implement the same interface so that the publishers isn’t coupled to concrete classes.
  • The Client creates publishers and subscribers objects separately and registers subscribers for updates.

Diagram

Observer Design Pattern Diagram

Use case

  • When changes to the state of one object may require changing other objects, and the actual set of objects is unknown beforehand or changes dynamically.
  • When some objects in your app must observe other, but only for a limited time or in specific cases.

State Pattern

Introduction

Behavorial design pattern that lets an object alter its behavior when its internal state changes. It appears as if the object changed its class.

Example

Suppose you want to make a blog. For this your documents can be in a finite number of states (Draft, Moderation, Published) than have transition between them with specific rules. At first, creating 3 separate classes that does their own work doesn’t feel too much work. But as you start adding new states and steps you realise this wasn’t a good idea as your methods become monstruous. You start seeing your processes as a graph and it starts feeling obvious that the state pattern is the pattern you need.

Implementation

  • A Context that stores a reference to the current Concrete State and delegates to it all state-specific work. The Context and Concrete States communicates via the State interface.
  • The State interface declares the state-specific methods.
  • The Concrete States provide their own implementation for the state-specific methods. Some intermediate abstract classes could implement common behavior.

Diagram

State Design Pattern Diagram

Use case

  • When you have an object that behaves differently depending on its current state, the number of states is enormous, and the state-specific code changes frequently.
  • When you have a class polluted with massive conditionals that alter how the class behaves according to the current values of the class’s fields.
  • When you have a lot of duplicate code across similar states and transitions of a condition-based state machine.

Strategy Pattern

Introduction

Behavorial design pattern that lets you define a family of algorithms, put each of them into a separate class, and make their objects interchangeable.

Example

You want to make a navigation map for sports usage. In the first version, you implement an algorithm for bycicle tours. Later you add a functionality for walks. When you start thinking about adding one for trailers, you realize your code is becoming messier as you add new features. To solve the mess, you figure about implementing the Strategy design pattern.

Implementation

  • A Context class that maintains a reference to one of the concrete strategies and communicate with it only via the Strategy interface.
  • A Strategy interface that is common to all concrete strategies. It declares a method to execute a strategy.
  • Concrete strategies implement different variables of an algorithm the context uses.
  • The Client creates a specific strategy object and passes it to the context.

Diagram

Strategy Design Pattern Diagram

Use case

  • When you want to use different variants of an algorithm within an object and be able to switch from one algorithm to another during runtime.
  • When you have a lot of similar classes that only differ in the way they execute some behavior.
  • To isolate the business logic of a class from the implementation details of algorithms that may not be as important in the context of that logic.
  • When your class has a massive conditional statement that switches between different variants of the same algorithm.

Template Pattern

Introduction

Behavorial design pattern that defines the skeleton of an algorithm in the superclass but lets subclasses override specific steps of the algorithm without changing its structure

Example

You decide to create a data mining application that can only work with Doc files at first. Later you add support for CSV files. And later again you add PDf files data extraction. You start figuring out that those 3 features share a lot of code and do things in the same order. Template design pattern lets you clean that code and provide easier implementation of similar features.

Implementation

  • An AbstractClass that declares methods that act as steps of an algorithm and a template method which calls these methods in a specific order.
  • Concrete classes that override some or all the steps but not the template method itself.

Diagram

Template Design Pattern Diagram

Use case

  • When you want to let clients extend only particular steps of an algorithm, but not the whole algorithm or its structure.
  • When you have several classes that contain almost identical algorithms with some minor differences.

Sources

Refactoring Guru