Design Patterns in Java

Creational :

Creational design patterns are used to design the instantiation process of objects.

1> Prototype Design Pattern

The Prototype design pattern is used to specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype. The concept is to copy an existing object rather than creating a new instance from scratch, something that may include costly operations.

The existing object acts as a prototype and contains the state of the object. The newly copied object may change some properties only if required. In Java, there are certain ways to copy an object in order to create a new one. One way to achieve this is using the Cloneable interface.

2> Builder Design Pattern

The Builder pattern suggests moving the construction logic out of the object class to a separate class referred to as a builder class. There can be more than one such builder classes, each with different implementations for the series of steps to construct the object. Builder Pattern in JDK:-

java.lang.StringBuilder#append() (unsynchronized) java.lang.StringBuffer#append() (synchronized)

3> Singleton Design Pattern

The Singleton Pattern ensures that a class has only one instance, and provides a global point of access to it.

There are some other ways to break the singleton pattern.

• If the class is Serializable.

• If it’s Clonable.

• It can be break by Reflection.

• And also if, the class is loaded by multiple class loaders.

     public class SingletoneEnum {
                public enum SingleEnum{
                    SINGLETON_ENUM;
                }
            }

4> Factory Method Design Pattern

The Factory Method Pattern gives us a way to encapsulate the instantiations of concrete types. The Factory Method pattern encapsulates the functionality required to select and instantiate an appropriate class, inside a designated method referred to as a factory method. The Factory method selects an appropriate class from a class hierarchy based on the application context and other influencing factors. It then instantiates the selected class and returns it as an instance of the parent class type.

Structural:-

Structural patterns are concerned with how classes and objects are composed to form larger structures. Structural class patterns use inheritance to compose interfaces or implementations.

1> Proxy Design pattern

The Proxy Pattern is used to create a representative object that controls access to another object, which may be remote, expensive to create or in need of being secured. One reason for controlling access to an object is to defer the full cost of its creation and initialization until we actually need to use it. Another reason could be to act as a local representative for an object that lives in a different JVM. In the Proxy Pattern, a client does not directly talk to the original object, it delegates it calls to the proxy object which calls the methods of the original object.

2> Decorator Design Pattern

Decorators provide a flexible alternative to sub-classing for extending functionality. The Decorator Pattern is used to extend the functionality of an object dynamically without having to change the original class source or using inheritance. This is accomplished by creating an object wrapper referred to as a Decorator around the actual object. The Decorator object is designed to have the same interface as the underlying object. This allows a client object to interact with the Decorator object in exactly the same manner as it would with the underlying actual object.

        public interface Pizza {
            public String getDesc();
            public double getPrice();
        }

        public class SimplyVegPizza implements Pizza

        public class SimplyNonVegPizza implements Pizza

        public abstract class PizzaDecorator implements Pizza

        public class Broccoli extends PizzaDecorator{
            private final Pizza pizza;
            public Broccoli(Pizza pizza){
                        this.pizza = pizza;
            }
        }
        public class Cheese extends PizzaDecorator{
            private final Pizza pizza;
            public Cheese(Pizza pizza){
                  this.pizza = pizza;
            }
        }

3> Facade Design Pattern

The Facade Pattern provides a unified interface to a set of interface in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use. The Facade unifies the complex low-level interfaces of a subsystem in-order to provide a simple way to access that interface.

4> Adapter Design Pattern

The Adapter pattern lets you to adapt what an object or a class exposes to what another object or class expects. It converts the interface of a class into another interface the client expects. It lets classes work together that couldn’t otherwise because of incompatible interfaces. An adapter uses composition to store the object it is supposed to adapt, and when the adapter’s methods are called, it translates those calls into something the adapted object can understand and passes the calls on to the adapted object.

5> Flyweight Design Pattern

The intent of the Flyweight Pattern is to use shared objects to support large numbers of fine-grained objects efficiently. A flyweight is a shared object that can be used in multiple contexts simultaneously.

E.g. Database connection objects that could be reshared.

Flyweight in the JDK:-

java.lang.Integer#valueOf(int)

Behavioral:-

Behavioral patterns are concerned with algorithms and the assignment of responsibilities between objects. Behavioral patterns describe not just patterns of objects or classes but also the patterns of communication between them. These patterns characterize complex control flow that’s difficult to follow at run-time. They shift your focus away from flow of control to let you concentrate just on the way objects are interconnected.

1> Chain of Responsibility Design Pattern

The Chain of Responsibility pattern is a behavior pattern in which a group of objects is chained together in a sequence and a responsibility (a request) is provided in order to be handled by the group. If an object in the group can process the particular request, it does so and returns the corresponding response. Otherwise, it forwards the request to the subsequent object in the group.

E.g. Exception Handling in Java.

2> Iterator Design Pattern

The intent of the Iterator Design Pattern is to provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.

An aggregate object, such as a list, should give you a way to access its elements without exposing its internal structure.

Iterator Pattern in JDK:-

• java.util.Iterator

• java.util.Enumeration

3> State Design Pattern

The State Design Pattern allows an object to alter its behavior when its internal state changes. The object will appear to change its class.

State Design Pattern in Java:-

• javax.faces.lifecycle.LifeCycle#execute()

4> Strategy Design Pattern

The Strategy Design Pattern defines a family of algorithms, encapsulating each one, and making them interchangeable. Strategy lets the algorithm vary independently from the clients that use it.

The Strategy 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.

Strategy Pattern in JDK:-

• java.util.Comparator#compare()

5> Observer Design Pattern

The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically. The Observer pattern describes these dependencies. The key objects in this pattern are subject and observer. A subject may have any number of dependent observers. All observers are notified whenever the subject undergoes a change in its state. In response, each observer will query the subject to synchronize its state with the subject state.

The other way to understand the Observer Pattern is the way Publisher-Subscriber relationship works.

Java has built-in support for the Observer Pattern. The most general is the Observer interface and the Observable class in the java.util package. These are quite similar to our Subject and Observer interface.

6> Visitor Design Pattern

The Visitor pattern is useful when designing an operation across a heterogeneous collection of objects of a class hierarchy. The Visitor pattern allows the operation to be defined without changing the class of any of the objects in the collection. To accomplish this, the Visitor pattern suggests defining the operation in a separate class referred to as a visitor class. This separates the operation from the object collection that it operates on. For every new operation to be defined, a new visitor class is created. Since the operation is to be performed across a set of objects, the visitor needs a way of accessing the public members of these objects.

7> Template Design Pattern

Let’s recall some important steps which are required to connect and insert data into the database. First, we need a driver according to the database we want to connect with. Then, we pass some credentials to the database, then, we prepare a statement, set data into the insert statement and insert it using the insert command. Later, we close all the connections, and optionally destroy all the connection objects.

The Template Method pattern can be used in situations when there is an algorithm, some steps of which could be implemented in multiple different ways. In such scenarios, the Template Method pattern suggests keeping the outline of the algorithm in a separate method referred to as a template method inside a class, which may be referred to as a template class, leaving out the specific implementations of the variant portions (steps that can be implemented in multiple different ways) of the algorithm to different subclasses of this class.

Template Pattern in JDK

• java.util.Collections#sort()

java.io.InputStream#read()

8> Command Design Pattern

The intent of the Command Design Pattern is to encapsulate a request as an object, thereby letting the developer to parameterize clients with different requests, queue or log requests, and support undoable operations.

Command Design Pattern in JDK

• java.lang.Runnable

9> Momento Design Pattern

The Memento Pattern’s intent is, without violating encapsulation, to capture and externalize an object’s internal state so that the object can be restored to this state later.

Sometimes it’s necessary to record the internal state of an object. This is required when implementing checkpoints and "undo" mechanisms that let users back out of tentative operations or recover from errors. You must save state information somewhere, so that you can restore objects to their previous conditions. But objects normally encapsulate some or all of their state, making it inaccessible to other objects and impossible to save externally. Exposing this state would violate encapsulation, which can compromise the application’s reliability and extensibility.

Memento Pattern in JDK

• java.util.Date

10> Mediator Design Pattern

The Mediator Pattern defines an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently. Rather than interacting directly with each other, objects ask the Mediator to interact on their behalf which results in reusability and loose coupling. It encapsulates the interaction between the objects and makes them independent from each other. This allows them to vary their interaction with other objects in a totally different way by implementing a different mediator. The Mediator helps to reduce the complexity of the classes. Each object no longer has to know in detail about how to interact with the other objects. The coupling between objects goes from tight and brittle to loose and agile.

Mediator Pattern in JDK

• java.util.concurrent.Executor#execute()

• java.util.Timer (all scheduleXXX() methods)

• java.lang.reflect.Method#invoke()