We discuss some of the most common design patterns in Java and how they can help you solve common coding issues. Learn more.
A design pattern is a well-established and documented solution to a common software problem. You can think of them as best practices used by knowledgeable and experienced software developers. In the quarter century since Java was first introduced, software developers have faced numerous general problems during software development. Over time, the most advantageous solutions were obtained through trial and error, along with a great deal of experimentation involving many ideas and approaches. These solutions have now been codified into a set of recognized design patterns. Professional software developers are expected to know at least some popular solutions to typical coding problems. With that in mind, this series will present some of the main benefits of using design patterns, list the different types of design patterns, and finally, provide a brief summary of the patterns for each category.
Jump to:
Since every application is different, following an established design pattern does not guarantee the absolute perfect solution to your specific challenge. However, design patterns offer many advantages over trying to go it alone. Here are just a few:
SEE: The Top Java Courses from TR Academy
The official reference book on design patterns is “Design Patterns – Elements of Reusable Object-Oriented Software”. It outlines 23 design patterns, which are broken down into three categories: Creational, Structural, and Behavioral patterns. We will also discuss some miscellaneous design patterns in this series. Here is more information on each category:
The rest of this programming tutorial will provide an overview of the Creational patterns; other patterns will be added here at a later date.
Creational design patterns provide solutions to instantiate an Object in the best possible way for a given situation. The “Design Patterns” book describes five creational design patterns:
Now, let’s explore each of these in more detail.
The Factory Design pattern is used when we have a superclass with multiple subclasses and, based on input, we need to return one of the subclasses. This pattern takes out the responsibility of the instantiation of a Class from the client program to the factory class. Developers can apply a Singleton Pattern on the factory class or make the factory method static.
For example, we could create some concrete classes that implement the Shape interface. Classes would then use the ShapeFactory class to get a Shape object, passing in information about the type of object it needs (i.e. circle, rectangle, square, etc.). The factory class uses an if-else or switch statement to decide which class to return:
public class ShapeFactory { // get object of type shape // based on ShapeType enum public Shape getShape(ShapeType shapeType){ if(shapeType == null){ return null; } if(shapeType == ShapeType.CIRCLE){ return new Circle(); } else if(shapeType == ShapeType.RECTANGLE){ return new Rectangle(); } else if(shapeType == ShapeType.SQUARE){ return new Square(); } return null; } }
The Abstract Factory Pattern takes the Factory Pattern up a notch by providing a factory of factories. In the Factory Design Pattern, you will typically have a single factory class that returns the different subclasses based on the input provided.
In the Abstract Factory Pattern, however, the if-else block of the above example would be replaced by multiple factory classes (one for each subclass). An abstract factory class then returns the subclass based on the input factory class.
The Singleton Pattern restricts the instantiation of a Class and ensures that only one instance of the class exists in the Java Virtual Machine (JVM). The implementation of the Singleton Pattern has always been a controversial topic among developers. The sticking point is that singletons remain in memory for the life of an application, making them a potential drain on system resources. On the other hand, having one object in memory is preferable to having many instances existing simultaneously.
The Prototype Pattern is used when the Object creation is costly and requires a lot of time and resources, and you have a similar Object that is already instantiated. Using the Prototype Pattern, programmers would copy the original Object to a new Object and then modify it according to their needs. Copying of the Object’s properties is achieved using Java cloning. The Prototype Design Pattern mandates that the Object which you are copying should provide the copying feature. It should not be done by any other class. However, whether to use the shallow or deep copy of the object properties depends on the requirements and is a design decision.
The Builder Pattern was introduced to solve some of the problems with Factory and Abstract Factory Design Patterns when the object contains a lot of attributes. This pattern solves the issue by introducing a large number of optional parameters. The object may also be in an inconsistent state and it may be built step-by-step. Lastly, the builder class provides a method that will actually return the final Object.
This first installment on Design Patterns in Java presented some of the main benefits of using design patterns, listed the different types of design patterns, and finally, provided a brief summary of the Creational Patterns. In part 2, we will be covering the Structural Patterns category. Stay tuned!
SEE: Java Programming Career Bundle