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:
Benefits of Java design patterns
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:
- Design patterns can speed up the development process by providing tested, proven development paradigms.
- They promote reusability and may be implemented across multiple projects.
- They help to define the system architecture.
- They help provide transparency to the design of an application.
- Using design patterns leads to more robust and highly maintainable code.
- Makes code easier to understand and debug.
SEE: The Top Java Courses from TR Academy
Types of design patterns
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:
- Creational Patterns: These design patterns provide a way to create objects while hiding the creation logic, rather than instantiating objects directly using the new operator. This gives programmers more flexibility in deciding which objects need to be created for a given use case.
- Structural Patterns: These design patterns concern class and object composition. The concept of inheritance is used to build interfaces and define ways to compose objects to obtain new functionalities.
- Behavioral Patterns: These design patterns address communication between objects.
- Miscellaneous Patterns: These design patterns are identified by the Sun Java Center and are mostly related to the presentation tier.
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 Patterns
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:
- Factory Pattern.
- Abstract Factory Pattern.
- Singleton Pattern.
- Prototype Pattern.
- Builder Pattern.
Now, let’s explore each of these in more detail.
Factory Pattern
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; } }
Abstract Factory Pattern
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.
Singleton Pattern
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.
Prototype Pattern
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.
Builder Pattern
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.
Going Forward
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!