SWE : Behavioral Design Pattern

Part 4 of Design Pattern series

Pisit J.
Sum up As A Service
8 min readMar 4, 2021

--

image

1. Chain of Responsibility

  • Keyword — middleware, handler.
  • Link several handlers in specific order of chain. While passing a request to the chain, each handler is asked whether it can process it.

Pros

  • Handler can decide not to pass the request to the chain and effectively stop any further processing.

Cons

  • Some requests may not reach the end of the chain.
  • Others may reach the end of the chain unhandled.

Example

Middleware — linkWith & check & checNext
Middleware — Concrete Class
setMiddleware
middleware.linkWith & setMiddleware
Output — UserExistsMiddleware — Login successfully
Output — ThrottlingMiddleware — Request limit

Reference

2. Command

  • Keyword — undo, queue.
  • Decouple classes that invoke operations — Invoker — from classes that perform these operations — Operator — by declaring the Command interface.
  • Command can be used to queue operations, schedule their execution, or execute them remotely.
  • Command can be used to implement reversible operations — undo & rollback mechanics.

Pros

  • You can introduce new Command into the app without breaking existing client code.

Cons

  • The code maybe more complicated because layer between senders and receivers is created.

Example — Queue with Command

You need to implement the collection of Command that is ready for execution in particular order.

Command — execute
Invoker — addCommand & executeCommand
Operator
Main
Output

Reference

Example — Undo with Command

You need to implement the Command history that contains all executed Command objects along with related backups of the application’s state.

Command — backup & undo & execute
Command History — push & pop
Editor — init Command
Editor — executeCommand & undo
Editor
Command
Command History — Backup & Undo

Reference

3. Interpreter

  • Keyword — parser.
  • Define & evaluate language grammar or expression by parsing context.
  • Use Case — Musician is example of Interpreter. The pitch of a sound and its duration can be represented in musical note. This note provides the language of music. Musician can reproduce the original pitch and duration of each sound by interpreting musical note.

Example

Main — Context & Interpreter
Output

Reference

4. Iterator

  • Provide a way to access the elements sequentially without exposing its underlying representation (data structure e.g. list, stack, tree).

Pros

  • You can reduce duplication of the traversal code across your application.
  • New traversal operations can be defined without changing its interface.

Cons

  • Apply Iterator can add more complexity if you only works with simple collections — Generalizing traverse with Iterator maybe less efficient than going through elements directly.

Example

Iterator — hasNext & next
Main

Reference

5. Mediator

  • Promote loose coupling by prohibiting direct communication between the components which you want to make independent of each other and communicate indirectly through Mediator, instead.

Pros

  • You can extract the communications between various components into a single Mediator, making it easier to comprehend and maintain. You can easily reuse each components.
  • You can introduce new mediators with no effect to the any existing components.

Cons

  • Over time, Mediator can evolve into a huge God Object.

6. Memento

  • Keyword — snapshot, undo, rollback
  • Capture and export internal state so that the object can later be restored to specific state.

Pros

  • Memento makes the object itself responsible for creating a snapshot of its state. No other object can read the snapshot, making the original object’s state data safe and secure.

Cons

  • The app might consume lots of RAM to maintain Memento— need tracking system to clear obsolete mementos.

Example

Memento — getState
Originator — setState, createMemento, restoreState
CareTaker — addMemento, popMemento
Main
Output

Reference

7. Null Object

  • Provide alternative solution that offers suitable default do nothing behavior (default value, initial value).

Example

AbstractCustomer
ValidCustomer
InvalidCustomer for Null Object
Main
Output

Reference

8. Observer

  • Keyword — subject & observer, publisher & subscriber.
  • Provide loose coupling by defining one-to-many relation of publisher & subscribers.
  • Publisher is responsible for maintaining a list of subscribers and notifying them of state changes by calling their update() operation.
  • Subscribers are responsible for subscribing or unsubscribing themselves on publisher.

Pros

  • You can introduce new subscriber or publisher without breaking things.
  • You can establish subscribe or unsubscribe at runtime — subscribers can join or leave the list whenever they need to.

Cons

  • Order of notification from publisher to subscribers depends on order in subscription list.

Example

Subscriber — execute
Publisher — subscribe & unsubscribe & notify
Main — subscribe & unsubscribe
4 subscription s— log on open, email on open, log on save & email on save — are notified.
only 2 remaining subscriptions — log on save & email on save — are notified.

Reference

9. State

  • Allow object to change its behavior when its internal state changes — You create new classes for all possible states of an object and extract all state-specific behaviors into these classes.
  • State-specific behavior should be defined independently — adding new states should not affect the behavior of existing states.
  • Use Case — The buttons in your smartphone behave differently depending on the current state of the device — When the phone is unlocked, pressing buttons leads to executing various functions. When the phone is locked, pressing any button leads to the unlock screen. When the phone’s charge is low, pressing any button shows the charging screen.

Pros

  • State is a good choice when you have a lot of states and state-specific behaviors. Also their logic are frequently changed.

Cons

  • State can be overkill if only a few states changes. — simple if-else or switch-case maybe more reasonable to implement.

10. Strategy

  • Identify an algorithm through a interface — Delegate the alternative implementations in derived classes.
  • Use Case — For sorting algorithm, you can implement by various methods such as bubble sort, merge sort & quick sort.

Pros

  • Strategy let you have different variants of an algorithm and you switch from one variant to another during runtime.

Cons

  • To implement Strategy, you need to introduce new classes and interfaces. So, if you only have a few variant of algorithms and they rarely change, there’s no reason to make things complicated.

Example

Strategy
Context — setStrategy & executeStrategy
Main

Reference

11. Template Method

  • Define the structure of steps and let subclasses override implementation of certain step, without changing the structure.

Pros

  • When you turn such an algorithm into Template Method, you can also extract the template steps into a superclass, eliminating code duplication. For each step, the variant implementations remain in subclasses.

Cons

  • The more steps Template Method have, The harder to maintain.

Example

Template & runTemplateMethod
Process extends Template
Another process extends Template
Main
Output

Reference

12. Visitor

  • Keyword — double dispatch.
  • Provide the new behavior as a separate class called Visitor, instead of trying to integrate it into existing classes. The existing classes are now passed to specific method of Visitor as an argument to execute that new behavior.

Pros

  • Open/Closed Principle — You can introduce a new behavior of different classes without modifying the classes themselves.
  • Visitor can gather data from each class they are working with.

Cons

  • You need to update Visitor each time a class added or removed from the class hierarchy.
  • You need to make sure that Visitor has necessary access to the private fields and methods of the each class.

Example

Existing Class — accept Visitor as argument.
Visitor with specific method — visit — for each existing class.
Main
Output

Reference

--

--