Monday, January 8, 2024

Behavioral patterns

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

The Template Method Pattern describes the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm’s structure.

 When to use the Template Design Pattern

  • To implement the invariant parts of an algorithm once and leave it up to subclasses to implement the behavior that can vary.
  • When common behavior among subclasses should be factored and localized in a common class to avoid code duplication. We should first identify the differences in the existing code and then separate the differences in new operations. Finally, replace the differing code with a template method that calls one of these new operations.

Usage in JDK

  • All non-abstract methods of java.io.InputStream, java.io.OutputStream, java.io.Reader and java.io.Writer. e.g. – java.io.InputStream#skip(), java.io.InputStream#read()
  • All non-abstract methods of java.util.AbstractList, java.util.AbstractSet and java.util.AbstractMap. e.g. – java.util.AbstractList#indexOf (), java.util.Collections#sort ().

 Mediator Design Pattern

Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently.

We use the Mediator Design Pattern to provide a centralized communication medium between different objects in a system.

When to use the Mediator Pattern

  1. A set of objects communicates in well-defined but complex ways. The resulting interdependencies are unstructured and difficult to understand.
  2. Reusing an object is difficult because it refers to and communicates with many other objects.
  3. A behavior that’s distributed between several classes should be customizable without a lot of sub-classing.

Mediator Pattern in JDK

  • util.Timer class scheduleXXX () methods.
  • Java Concurrency Executor execute () method.
  • lang.reflect.Method invoke () method.

 Chain Of Responsibility Design Pattern

When there are more than one objects that can handle or fulfill a client request, the pattern recommends giving each of these objects a chance to process the request in some sequential order. Applying the pattern in such a case, each of these potential handlers can be arranged in the form of a chain, with each object having a reference to the next object in the chain.

 The first object in the chain receives the request and decides either to handle the request or to pass it on to the next object in the chain. The request flows through all objects in the chain one after the other until the request is handled by one of the handlers in the chain or the request reaches the end of the chain without getting processed.

When to use the Chain of Responsibility Pattern

Use Chain of Responsibility when

  1. More than one object may handle a request, and the handler isn’t known a priori. The handler should be ascertained automatically.
  2. You want to issue a request to one of several objects without specifying the receiver explicitly.
  3. The set of objects that can handle a request should be specified dynamically.

Chain of Responsibility Pattern Examples in JDK

  • util.logging.Logger#log ()
  • servlet.Filter#doFilter ()

Observer Design Pattern

In observer design pattern multiple observer objects registers with a subject for any change in notification. When the state of subject changes, it notifies the observers. Objects that listen or watch for change are called observers and the object that is being watched is called a subject. Pattern involved is also called as publish-subscribe pattern.

When to use the Observer Pattern

Use the Observer pattern in any of the following situations:

  1. When an abstraction has two aspects, one dependent on the other. Encapsulating these aspects in separate objects lets you vary and reuse them independently.
  2. When a change to one object requires changing others, and you don’t know how many objects need to be changed?
  3. When an object should be able to notify other objects without making assumptions about who these objects are. In other words, you don’t want tight coupling in these objects.

Usage in Java

  • util.EventListener in Swing
  • servlet.http.HttpSessionBindingListener
  • servlet.http.HttpSessionAttributeListener

 Strategy Design Pattern

The Strategy Design Pattern is useful when there is a set of related algorithms and a client object needs to be able to dynamically pick and choose an algorithm from this set that suits its current need. The Strategy pattern suggests keeping the implementation of each of the algorithms in a separate class. Each such algorithm encapsulated in a separate class is referred to as a Strategy. An object that uses a Strategy object is often referred to as a context object.

We use Strategy Pattern when we have multiple algorithms for a specific task and client decides the actual implementation to be used at runtime.

When to use the Strategy Design Pattern

Use the Strategy pattern when:

  • Many related classes differ only in their behavior as Strategies provide a way to configure a class with one of many behaviors.
  • You need different variants of an algorithm. For example, you might define algorithms reflecting different space/time trade-offs. Here, we can use Strategies when the implementation of these variants are as a class hierarchy of algorithms.
  • An algorithm uses data that clients shouldn’t know about. Use the Strategy pattern to avoid exposing complex, algorithm-specific data structures.
  • A class defines many behaviors, and these appear as multiple conditional statements in its operations. Instead of many conditionals, move related conditional branches into their own Strategy class.

Strategy Pattern in JDK

  • util.Comparator#compare ()
  • servlet.http.HttpServlet
  • servlet.Filter#doFilter ()

Command Design Pattern

The Command Pattern is a behavioral object design pattern. In the command pattern, a Command interface declares a method for executing a particular action. Concrete Command classes implement the execute () method of the Command interface, and this execute () method invokes the appropriate action method of a Receiver class that the Concrete Command class contains.

When to use the Command Design Pattern

Use the Command pattern when you want to:

  • Parameterize objects by an action to perform.
  • Structure a system around high-level operations built on primitives’ operations. Such a structure is common in information systems that support transactions. Moreover, the Command Pattern offers a way to model transactions. Commands have a common interface, letting you invoke all transactions the same way. The pattern also makes it easy to extend the system with new transactions.
  • The Command’s Execute operation can store state for reversing its effects in the command itself. The Command interface must have an added Un-execute operation that reverses the effects of a previous call to Execute. We can store the executed commands  in a history list. Also, we can achieve Unlimited-level undo and redo by traversing this list backwards and forwards calling Un-execute and Execute, respectively. It supports undo as well.

Command Pattern JDK Example

Runnable interface (java.lang.Runnable) and Swing Action (javax.swing.Action) uses command pattern.

Visitor Design Pattern

When we have to perform an operation on a group of similar kind of Objects, we use Visitor Pattern. With the help of visitor pattern, we can move the operational logic from the objects to another class. For example, think of a Shopping cart where we can add different type of items (Elements), when we click on the checkout button, it calculates the total amount that we need to pay. Now, we can have the calculation logic in item classes or we can move out this logic to another class using Visitor Pattern. So, using visitor pattern we can move out logics to another class. 

When to use the Visitor Design Pattern

Use the Visitor pattern when:

  • An object structure contains many classes of objects with differing interfaces, and you want to perform operations on these objects that depend on their concrete classes.
  • When we need to perform many distinct and unrelated operations on objects in an object structure, and we want to avoid “polluting” their classes with these operations. Visitor lets you keep related operations together by defining them in one class. When we need to share the object structure with many applications, use Visitor to put operations in just those applications that need them.
  • The classes defining the object structure rarely change, but you often want to define new operations over the structure. However, changing the object structure classes requires redefining the interface to all visitors, which is potentially costly. If the object structure classes change often, then it’s probably better to define the operations in those classes.

Visitor Design Pattern in JDK

  • lang.model.element.Element and javax.lang.model.element.ElementVisitor
  • lang.model.type.TypeMirror and javax.lang.model.type.TypeVisitor

State Design Pattern

We use State Design Pattern when an Object changes its behavior on change of its internal state. We can define the state of an object as its exact condition at any given point of time, depending on the values of its properties or attributes. The set of methods implemented by a class constitutes the behavior of its instances. Whenever there is a change in the values of its attributes, we say that the state of an object has changed.

When to use the State Design Pattern

Use the State pattern in either of the following cases:

  • When an object’s behavior depends on its state, and it must change its behavior at run-time depending on its state.
  • When operations have large, multipart conditional statements that depend on the object’s state. This state is usually represented by one or more enumerated constants. Often, several operations will contain this same conditional structure. The State Pattern puts each branch of the conditional in a separate class. This lets us treat the object’s state as an object in its own right that can vary independently from other objects.

State Design Pattern in Java

  • faces.lifecycle.LifeCycle#execute()

Iterator Design Pattern

Iterator Pattern in one of the behavioral patterns and we use it to provide a standard way to traverse through a group of Objects. We widely use the Iterator Pattern in Java Collection Framework where Iterator interface provides methods for traversing through a collection

When to use the Iterator Design Pattern

Use the Iterator pattern:

  • When you want to provide a standard way to iterate over a collection and hide the implementation logic from client program.
  • When you need to access an aggregate object’s contents without exposing its internal representation.
  • To support multiple traversals of aggregate objects.
  • To provide a uniform interface for traversing different aggregate structures (that is, to support polymorphic iteration).

Iterator Pattern in JDK

  • util.Iterator
  • util.Enumeration

Interpreter Design Pattern

Interpreter Pattern is one of the behavioral design patterns and we use it to define a grammatical representation for a language and it provides an interpreter to deal with the grammar. The best example of this pattern is java compiler that interprets the java source code into byte code that is understandable by JVM. Google Translator is also an example of interpreter pattern where the input can be in any language and we can get the interpreted output in another language.

When to use the Interpreter Design Pattern

Use the Interpreter pattern when there is a language to interpret, and you can represent statements in the language as abstract syntax trees. The Interpreter pattern works best when

  • The grammar is simple. For complex grammars, the class hierarchy for the grammar becomes large and unmanageable. Tools such as parser generators are a better alternative in such cases. They can interpret expressions without building abstract syntax trees, which can save space and possibly time also.
  • Efficiency is not a critical concern. The most efficient interpreters are usually not implemented by interpreting parse trees directly but by first translating them into another form. For example, regular expressions are often transformed into state machines. But even then, we can implement the translator with the help of Interpreter pattern, so the pattern is still applicable.

Interpreter Design Pattern in JDK

  • util.Pattern
  • text.Normalizer
  • text.Format

 Memento Design Pattern

Memento pattern is one of the behavioral design patterns. We use Memento Design Pattern when we want to save the state of an object so that we can restore it later on. Memento pattern helps to implement this in such a way that the saved state data of the object is not accessible outside of the object; this protects the integrity of saved state data.

When to use the Memento Pattern

Use the Memento Pattern in the following cases:

  • A snapshot of (some portion of) an object’s state must be saved so that it can be restored to that state later, and
  • A direct interface to obtain the state would expose implementation details and break the object’s encapsulation.

Memento Pattern in JDK

  • java.util.Date
  • java.io.Serializable

 

No comments:

Post a Comment