For working professionals
For fresh graduates
More
6. JDK in Java
7. C++ Vs Java
16. Java If-else
18. Loops in Java
20. For Loop in Java
46. Packages in Java
53. Java Collection
56. Generics In Java
57. Java Interfaces
60. Streams in Java
63. Thread in Java
67. Deadlock in Java
74. Applet in Java
75. Java Swing
76. Java Frameworks
78. JUnit Testing
81. Jar file in Java
82. Java Clean Code
86. Java 8 features
87. String in Java
93. HashMap in Java
98. Enum in Java
101. Hashcode in Java
105. Linked List in Java
109. Array Length in Java
111. Split in java
112. Map In Java
115. HashSet in Java
118. DateFormat in Java
121. Java List Size
122. Java APIs
128. Identifiers in Java
130. Set in Java
132. Try Catch in Java
133. Bubble Sort in Java
135. Queue in Java
142. Jagged Array in Java
144. Java String Format
145. Replace in Java
146. charAt() in Java
147. CompareTo in Java
151. parseInt in Java
153. Abstraction in Java
154. String Input in Java
156. instanceof in Java
157. Math Floor in Java
158. Selection Sort Java
159. int to char in Java
164. Deque in Java
172. Trim in Java
173. RxJava
174. Recursion in Java
175. HashSet Java
177. Square Root in Java
190. Javafx
Design patterns in Java are proven solutions to common programming problems. They represent best practices evolved over time by experienced developers. Design patterns provide templates for solving specific issues in software design. These templates help create more maintainable and flexible code. They enable developers to use tested, proven development paradigms.
Design patterns establish a common vocabulary for discussing complex programming concepts. They serve as building blocks for constructing larger, more complex applications. Most patterns focus on object-oriented programming principles like encapsulation and inheritance.
They save time by providing ready-made solutions to recurring problems. Many online Software Engineering courses emphasize design patterns as essential knowledge for Java developers.
Design patterns in Java are reusable solutions to common problems in software design. They represent best practices that have evolved through collective experience. These patterns are not complete designs that can be transformed directly into code. Instead, they serve as templates that can be applied to different situations.
Design patterns in Java generally fall into three main categories:
Take your skills to the next level with these highly rated courses.
Each pattern describes a problem that occurs repeatedly in our environment. It then describes the core solution to that problem. This solution can be applied multiple times without doing the same thing twice.
// A simple example showing the concept of design patterns
public class DesignPatternConcept {
public static void main(String[] args) {
// Without design pattern - direct instantiation
Database mysqlDirectly = new MySQLDatabase();
mysqlDirectly.connect();
// With Factory design pattern
DatabaseFactory factory = new DatabaseFactory();
Database mysql = factory.getDatabase("MySQL");
mysql.connect();
}
}
// The Factory approach allows for more flexibility and abstraction
Output:
Connected to MySQL Database directly
Connected to MySQL Database through factory
Explanation:
This simple example illustrates the concept of design patterns. Without a design pattern, we directly instantiate a specific database class. With the Factory pattern, we use a factory class that creates the appropriate database object based on a parameter. This adds a layer of abstraction and flexibility that makes the code more maintainable.
Design patterns in Java help developers solve problems efficiently. They promote code reuse and make applications more robust. However, they should be applied judiciously to avoid unnecessary complexity.
Must read: Stack and Heap Memory in Java: Key Differences Explained
The Factory design pattern in Java is a creational pattern that provides an interface for creating objects. It allows subclasses to alter the type of objects created. This pattern hides the creation logic from the client code.
The Factory design pattern in Java creates objects without exposing the creation logic. The client uses the same common interface to create new types of objects. The factory class decides which concrete implementation to instantiate.
This pattern decouples the client code from the object creation code. It promotes loose coupling, which means objects have fewer dependencies on each other. The factory pattern relies on inheritance and polymorphism to achieve its goals.
You should consider using the factory design pattern in Java in several scenarios:
The factory pattern is particularly useful when working with complex object creation. It helps manage complexity by centralizing the creation logic. It also supports the principle of programming to an interface, not an implementation.
When to use factory design pattern in Java depends on how much flexibility you need. Use it when you want to decouple object creation from its use. This makes your code more maintainable and testable.
Must explore: Conditional Operators in Java
Here's a complete example of the factory design pattern in Java:
// Step 1: Define the product interface
interface Vehicle {
void drive();
}
// Step 2: Create concrete product classes
class Car implements Vehicle {
@Override
public void drive() {
System.out.println("Driving a car");
}
}
class Motorcycle implements Vehicle {
@Override
public void drive() {
System.out.println("Riding a motorcycle");
}
}
class Truck implements Vehicle {
@Override
public void drive() {
System.out.println("Driving a truck");
}
}
// Step 3: Create the factory class
class VehicleFactory {
// The factory method
public Vehicle createVehicle(String vehicleType) {
if (vehicleType == null) {
return null;
}
if (vehicleType.equalsIgnoreCase("CAR")) {
return new Car();
} else if (vehicleType.equalsIgnoreCase("MOTORCYCLE")) {
return new Motorcycle();
} else if (vehicleType.equalsIgnoreCase("TRUCK")) {
return new Truck();
}
return null;
}
}
// Step 4: Client code that uses the factory
public class FactoryPatternDemo {
public static void main(String[] args) {
// Create the factory
VehicleFactory factory = new VehicleFactory();
// Use the factory to create different vehicles
Vehicle car = factory.createVehicle("CAR");
car.drive();
Vehicle motorcycle = factory.createVehicle("MOTORCYCLE");
motorcycle.drive();
Vehicle truck = factory.createVehicle("TRUCK");
truck.drive();
}
}
Driving a car
Riding a motorcycle
Driving a truck
This implementation demonstrates the factory design pattern in Java. The VehicleFactory class acts as a factory that creates different types of vehicles. The client code creates a factory object and then uses it to create various vehicle objects. The client doesn't need to know the specific classes of vehicles being created, it just works with the Vehicle interface. This achieves loose coupling between the client code and the concrete implementations.
Check out: Arithmetic Operators in Java
The Builder design pattern in Java separates the construction of complex objects from their representation. It allows the same construction process to create different representations.
The Builder design pattern in Java constructs complex objects step by step. It separates the construction of a complex object from its representation. The same construction process can create different representations.
This pattern is especially useful when an object has many parameters. Some parameters might be optional, making constructor overloading cumbersome. The Builder pattern provides a clear solution to this "telescoping constructor" problem.
What is builder design pattern in Java? It's a creational pattern that lets you construct complex objects step by step. It allows you to produce different types and representations of an object using the same construction code.
Here's a complete implementation of the builder design pattern in Java:
// Product class
class House {
private String foundation;
private String structure;
private String roof;
private String interior;
public void setFoundation(String foundation) {
this.foundation = foundation;
}
public void setStructure(String structure) {
this.structure = structure;
}
public void setRoof(String roof) {
this.roof = roof;
}
public void setInterior(String interior) {
this.interior = interior;
}
@Override
public String toString() {
return "House with " + foundation + " foundation, " +
structure + " structure, " +
roof + " roof, and " +
interior + " interior";
}
}
// Abstract Builder
interface HouseBuilder {
void buildFoundation();
void buildStructure();
void buildRoof();
void buildInterior();
House getResult();
}
// Concrete Builder for a Wooden House
class WoodenHouseBuilder implements HouseBuilder {
private House house;
public WoodenHouseBuilder() {
this.house = new House();
}
@Override
public void buildFoundation() {
house.setFoundation("wooden");
}
@Override
public void buildStructure() {
house.setStructure("wooden frames");
}
@Override
public void buildRoof() {
house.setRoof("wooden shingles");
}
@Override
public void buildInterior() {
house.setInterior("rustic wooden");
}
@Override
public House getResult() {
return house;
}
}
// Concrete Builder for a Concrete House
class ConcreteHouseBuilder implements HouseBuilder {
private House house;
public ConcreteHouseBuilder() {
this.house = new House();
}
@Override
public void buildFoundation() {
house.setFoundation("concrete");
}
@Override
public void buildStructure() {
house.setStructure("concrete blocks");
}
@Override
public void buildRoof() {
house.setRoof("concrete tiles");
}
@Override
public void buildInterior() {
house.setInterior("modern minimalist");
}
@Override
public House getResult() {
return house;
}
}
// Director
class ConstructionEngineer {
private HouseBuilder houseBuilder;
public ConstructionEngineer(HouseBuilder houseBuilder) {
this.houseBuilder = houseBuilder;
}
public House constructHouse() {
houseBuilder.buildFoundation();
houseBuilder.buildStructure();
houseBuilder.buildRoof();
houseBuilder.buildInterior();
return houseBuilder.getResult();
}
}
// Client code
public class BuilderPatternDemo {
public static void main(String[] args) {
// Construct a wooden house
HouseBuilder woodenBuilder = new WoodenHouseBuilder();
ConstructionEngineer engineer = new ConstructionEngineer(woodenBuilder);
House woodenHouse = engineer.constructHouse();
System.out.println(woodenHouse);
// Construct a concrete house using the same construction process
HouseBuilder concreteBuilder = new ConcreteHouseBuilder();
engineer = new ConstructionEngineer(concreteBuilder);
House concreteHouse = engineer.constructHouse();
System.out.println(concreteHouse);
}
}
House with wooden foundation, wooden frames structure, wooden shingles roof, and rustic wooden interior
House with concrete foundation, concrete blocks structure, concrete tiles roof, and modern minimalist interior
This implementation demonstrates the builder design pattern in Java. We have a House class (the product), HouseBuilder interface (the abstract builder), and concrete builders (WoodenHouseBuilder and ConcreteHouseBuilder). The ConstructionEngineer class acts as a director that follows a specific sequence to build houses. The client creates a builder and passes it to the director, which then uses the builder to construct and return the product. This pattern allows for step-by-step construction of complex objects with different representations using the same construction process.
The Singleton design pattern in Java ensures a class has only one instance. It provides a global point of access to this instance.
The Singleton design pattern in Java restricts the instantiation of a class to one single instance. It provides a global point of access to that instance throughout the application.
This pattern involves a single class responsible for creating its own object. This class ensures that only one instance gets created. It provides a way to access its only instance directly without instantiating the object of the class.
What is singleton design pattern in Java? It's a creational pattern that guarantees a class has only one instance and provides a global point to access it. It's used when exactly one object is needed to coordinate actions across the system.
Here's a complete implementation of the singleton design pattern in Java:
// Basic Singleton Pattern
class BasicSingleton {
// Private static instance variable
private static BasicSingleton instance;
// Private constructor to prevent instantiation
private BasicSingleton() {
System.out.println("BasicSingleton instance created");
}
// Public static method to get the instance
public static BasicSingleton getInstance() {
// Lazy initialization - create instance only when needed
if (instance == null) {
instance = new BasicSingleton();
}
return instance;
}
// Example method
public void showMessage() {
System.out.println("Hello from BasicSingleton!");
}
}
// Thread-safe Singleton Pattern using synchronized method
class ThreadSafeSingleton {
private static ThreadSafeSingleton instance;
private ThreadSafeSingleton() {
System.out.println("ThreadSafeSingleton instance created");
}
// Synchronized method to handle thread safety
public static synchronized ThreadSafeSingleton getInstance() {
if (instance == null) {
instance = new ThreadSafeSingleton();
}
return instance;
}
public void showMessage() {
System.out.println("Hello from ThreadSafeSingleton!");
}
}
// Thread-safe Singleton Pattern using double-checked locking
class DoubleCheckedSingleton {
// Volatile keyword ensures the instance is correctly published
private static volatile DoubleCheckedSingleton instance;
private DoubleCheckedSingleton() {
System.out.println("DoubleCheckedSingleton instance created");
}
public static DoubleCheckedSingleton getInstance() {
// Check once before entering synchronized block
if (instance == null) {
// Synchronize only during the first access
synchronized (DoubleCheckedSingleton.class) {
// Check again after entering synchronized block
if (instance == null) {
instance = new DoubleCheckedSingleton();
}
}
}
return instance;
}
public void showMessage() {
System.out.println("Hello from DoubleCheckedSingleton!");
}
}
// Singleton Pattern using static initialization
class EagerSingleton {
// Instance created at class loading time
private static final EagerSingleton INSTANCE = new EagerSingleton();
private EagerSingleton() {
System.out.println("EagerSingleton instance created");
}
public static EagerSingleton getInstance() {
return INSTANCE;
}
public void showMessage() {
System.out.println("Hello from EagerSingleton!");
}
}
// Singleton Pattern using enum (Java 5+)
enum EnumSingleton {
INSTANCE;
EnumSingleton() {
System.out.println("EnumSingleton instance created");
}
public void showMessage() {
System.out.println("Hello from EnumSingleton!");
}
}
// Client code
public class SingletonPatternDemo {
public static void main(String[] args) {
// Test BasicSingleton
BasicSingleton basicSingleton1 = BasicSingleton.getInstance();
BasicSingleton basicSingleton2 = BasicSingleton.getInstance();
basicSingleton1.showMessage();
System.out.println("Same instance? " + (basicSingleton1 == basicSingleton2));
// Test ThreadSafeSingleton
ThreadSafeSingleton threadSafeSingleton = ThreadSafeSingleton.getInstance();
threadSafeSingleton.showMessage();
// Test DoubleCheckedSingleton
DoubleCheckedSingleton doubleCheckedSingleton = DoubleCheckedSingleton.getInstance();
doubleCheckedSingleton.showMessage();
// Test EagerSingleton
EagerSingleton eagerSingleton = EagerSingleton.getInstance();
eagerSingleton.showMessage();
// Test EnumSingleton
EnumSingleton enumSingleton = EnumSingleton.INSTANCE;
enumSingleton.showMessage();
}
}
BasicSingleton instance created
Hello from BasicSingleton!
Same instance? true
ThreadSafeSingleton instance created
Hello from ThreadSafeSingleton!
DoubleCheckedSingleton instance created
Hello from DoubleCheckedSingleton!
EagerSingleton instance created
Hello from EagerSingleton!
EnumSingleton instance created
Hello from EnumSingleton!
This implementation demonstrates several variations of the singleton design pattern in Java:
In the output, we can see that BasicSingleton only creates one instance, even when getInstance() is called twice. This confirms that all implementations correctly maintain the singleton property.
The Adapter design pattern in Java allows classes with incompatible interfaces to work together. It acts as a bridge between two incompatible interfaces.
The Adapter design pattern in Java converts the interface of a class into another interface that clients expect. It lets classes work together that couldn't otherwise because of incompatible interfaces.
This pattern involves a single class called the Adapter. This class joins functionalities of independent or incompatible interfaces. It works as a bridge between two incompatible interfaces.
There are two types of adapter patterns:
Here's a complete implementation of the adapter design pattern in Java:
// Target interface that the client expects to work with
interface MediaPlayer {
void play(String audioType, String fileName);
}
// Existing interface that needs adapting
interface AdvancedMediaPlayer {
void playMp4(String fileName);
void playVlc(String fileName);
}
// Concrete implementations of AdvancedMediaPlayer
class Mp4Player implements AdvancedMediaPlayer {
@Override
public void playMp4(String fileName) {
System.out.println("Playing MP4 file: " + fileName);
}
@Override
public void playVlc(String fileName) {
// Do nothing
}
}
class VlcPlayer implements AdvancedMediaPlayer {
@Override
public void playMp4(String fileName) {
// Do nothing
}
@Override
public void playVlc(String fileName) {
System.out.println("Playing VLC file: " + fileName);
}
}
// Adapter class that makes AdvancedMediaPlayer compatible with MediaPlayer
class MediaAdapter implements MediaPlayer {
private AdvancedMediaPlayer advancedMusicPlayer;
public MediaAdapter(String audioType) {
if (audioType.equalsIgnoreCase("vlc")) {
advancedMusicPlayer = new VlcPlayer();
} else if (audioType.equalsIgnoreCase("mp4")) {
advancedMusicPlayer = new Mp4Player();
}
}
@Override
public void play(String audioType, String fileName) {
if (audioType.equalsIgnoreCase("vlc")) {
advancedMusicPlayer.playVlc(fileName);
} else if (audioType.equalsIgnoreCase("mp4")) {
advancedMusicPlayer.playMp4(fileName);
}
}
}
// Concrete implementation of MediaPlayer that uses the adapter
class AudioPlayer implements MediaPlayer {
private MediaAdapter mediaAdapter;
@Override
public void play(String audioType, String fileName) {
// Built-in support for mp3 files
if (audioType.equalsIgnoreCase("mp3")) {
System.out.println("Playing MP3 file: " + fileName);
}
// MediaAdapter provides support for other formats
else if (audioType.equalsIgnoreCase("vlc") || audioType.equalsIgnoreCase("mp4")) {
mediaAdapter = new MediaAdapter(audioType);
mediaAdapter.play(audioType, fileName);
} else {
System.out.println("Invalid media. " + audioType + " format not supported");
}
}
}
// Client code
public class AdapterPatternDemo {
public static void main(String[] args) {
AudioPlayer audioPlayer = new AudioPlayer();
// Play mp3 file - native support
audioPlayer.play("mp3", "song.mp3");
// Play mp4 file - adapter support
audioPlayer.play("mp4", "video.mp4");
// Play vlc file - adapter support
audioPlayer.play("vlc", "movie.vlc");
// Play unsupported format
audioPlayer.play("avi", "video.avi");
}
}
Playing MP3 file: song.mp3
Playing MP4 file: video.mp4
Playing VLC file: movie.vlc
Invalid media. avi format not supported
This implementation demonstrates the adapter design pattern in Java. We have a MediaPlayer interface (the target) and an incompatible AdvancedMediaPlayer interface. The MediaAdapter class adapts the AdvancedMediaPlayer interface to the MediaPlayer interface. The AudioPlayer class can now play not only MP3 files (natively) but also VLC and MP4 files (through the adapter). The client code creates an AudioPlayer and uses it to play different types of media. This pattern allows two incompatible interfaces to work together through an intermediate adapter class.
Design patterns in Java are powerful tools. However, they should be used appropriately to gain maximum benefit.
Design patterns should be applied when they truly solve a problem. Don't force a pattern into your code just because it seems sophisticated. Here are some guidelines:
Here are common mistakes when working with design patterns in Java:
Here's a comparison of the design patterns we've discussed:
Pattern | Type | Purpose | When to Use |
Factory | Creational | Creates objects without specifying exact class | When object creation logic should be separated from client code |
Builder | Creational | Constructs complex objects step by step | When an object has many parameters, especially optional ones |
Singleton | Creational | Ensures a class has only one instance | When exactly one object is needed throughout the application |
Adapter | Structural | Makes incompatible interfaces work together | When existing classes need to work with others without modifying source |
Create a system that can convert documents from various formats (PDF, Word, Text) to other formats using different design patterns.
import java.util.HashMap;
import java.util.Map;
// Document interface
interface Document {
String getContent();
String getFormat();
}
// Concrete document classes
class PdfDocument implements Document {
private String content;
public PdfDocument(String content) {
this.content = content;
}
@Override
public String getContent() {
return content;
}
@Override
public String getFormat() {
return "PDF";
}
}
class WordDocument implements Document {
private String content;
public WordDocument(String content) {
this.content = content;
}
@Override
public String getContent() {
return content;
}
@Override
public String getFormat() {
return "WORD";
}
}
class TextDocument implements Document {
private String content;
public TextDocument(String content) {
this.content = content;
}
@Override
public String getContent() {
return content;
}
@Override
public String getFormat() {
return "TEXT";
}
}
// Factory Pattern: Document Factory
class DocumentFactory {
public Document createDocument(String type, String content) {
if (type.equalsIgnoreCase("PDF")) {
return new PdfDocument(content);
} else if (type.equalsIgnoreCase("WORD")) {
return new WordDocument(content);
} else if (type.equalsIgnoreCase("TEXT")) {
return new TextDocument(content);
}
throw new IllegalArgumentException("Unknown document type: " + type);
}
}
// Converter interface
interface Converter {
Document convert(Document source, String targetFormat);
}
// Singleton Pattern: ConverterRegistry
class ConverterRegistry {
private static ConverterRegistry instance;
private Map<String, Converter> converters = new HashMap<>();
private ConverterRegistry() {
// Private constructor
}
public static synchronized ConverterRegistry getInstance() {
if (instance == null) {
instance = new ConverterRegistry();
}
return instance;
}
public void registerConverter(String key, Converter converter) {
converters.put(key, converter);
}
public Converter getConverter(String sourceFormat, String targetFormat) {
String key = sourceFormat + "To" + targetFormat;
return converters.get(key);
}
}
// Adapter Pattern: Convert PDF to Text
class PdfToTextConverter implements Converter {
@Override
public Document convert(Document source, String targetFormat) {
if (!source.getFormat().equals("PDF") || !targetFormat.equals("TEXT")) {
throw new IllegalArgumentException("Invalid conversion");
}
// In a real implementation, this would contain PDF parsing logic
String extractedText = "Extracted text from PDF: " + source.getContent();
return new TextDocument(extractedText);
}
}
// Adapter Pattern: Convert Word to Text
class WordToTextConverter implements Converter {
@Override
public Document convert(Document source, String targetFormat) {
if (!source.getFormat().equals("WORD") || !targetFormat.equals("TEXT")) {
throw new IllegalArgumentException("Invalid conversion");
}
// In a real implementation, this would contain Word parsing logic
String extractedText = "Extracted text from Word: " + source.getContent();
return new TextDocument(extractedText);
}
}
// Builder Pattern: DocumentBuilder for creating more complex documents
class DocumentBuilder {
private String format;
private String content = "";
private String title = "";
private String author = "";
private String creationDate = "";
public DocumentBuilder setFormat(String format) {
this.format = format;
return this;
}
public DocumentBuilder setContent(String content) {
this.content = content;
return this;
}
public DocumentBuilder setTitle(String title) {
this.title = title;
return this;
}
public DocumentBuilder setAuthor(String author) {
this.author = author;
return this;
}
public DocumentBuilder setCreationDate(String date) {
this.creationDate = date;
return this;
}
public Document build() {
// Enrich content with metadata
String enrichedContent = "Title: " + title + "\n" +
"Author: " + author + "\n" +
"Date: " + creationDate + "\n" +
"Content: " + content;
// Use the factory to create the appropriate document
DocumentFactory factory = new DocumentFactory();
return factory.createDocument(format, enrichedContent);
}
}
// Client code using all the patterns
public class DocumentConverterSystem {
public static void main(String[] args) {
// Initialize the registry (Singleton)
ConverterRegistry registry = ConverterRegistry.getInstance();
// Register converters
registry.registerConverter("PDFToTEXT", new PdfToTextConverter());
registry.registerConverter("WORDToTEXT", new WordToTextConverter());
// Create a document using Builder pattern
Document pdfDoc = new DocumentBuilder()
.setFormat("PDF")
.setContent("This is a sample PDF content")
.setTitle("Sample PDF")
.setAuthor("John Doe")
.setCreationDate("2023-05-15")
.build();
System.out.println("Original document:");
System.out.println("Format: " + pdfDoc.getFormat());
System.out.println("Content: " + pdfDoc.getContent());
System.out.println();
// Use Factory pattern to create another document
DocumentFactory factory = new DocumentFactory();
Document wordDoc = factory.createDocument("WORD", "This is a Word document");
// Convert documents using Adapter pattern via the registry
Converter pdfToTextConverter = registry.getConverter("PDF", "TEXT");
Document convertedPdf = pdfToTextConverter.convert(pdfDoc, "TEXT");
Converter wordToTextConverter = registry.getConverter("WORD", "TEXT");
Document convertedWord = wordToTextConverter.convert(wordDoc, "TEXT");
// Display results
System.out.println("Converted PDF to Text:");
System.out.println(convertedPdf.getContent());
System.out.println();
System.out.println("Converted Word to Text:");
System.out.println(convertedWord.getContent());
}
}
Original document:
Format: PDF
Content: Title: Sample PDF
Author: John Doe
Date: 2023-05-15
Content: This is a sample PDF content
Converted PDF to Text:
Extracted text from PDF: Title: Sample PDF
Author: John Doe
Date: 2023-05-15
Content: This is a sample PDF content
Converted Word to Text:
Extracted text from Word: This is a Word document
This implementation demonstrates a document converter system using multiple design patterns:
The client code shows how these patterns work together to create a flexible document conversion system. It creates documents using both the Factory and Builder patterns, registers converters in the Singleton registry, and uses the Adapter pattern to convert between different formats. This combination of patterns creates a modular, extensible system that can be easily enhanced with new document types and converters.
Design patterns in Java provide proven solutions to common programming problems. They help developers create more maintainable and flexible code. Factory patterns create objects without exposing the instantiation logic. Builder patterns construct complex objects step by step. Singleton patterns ensure a class has only one instance. Adapter patterns make incompatible interfaces work together.
These patterns serve as templates rather than finished designs. They should be applied appropriately to solve specific problems. Understanding when to use each pattern is as important as knowing how. Design patterns establish a common vocabulary among developers. They promote code reuse and reduce development time.
A design pattern in Java is a reusable solution to common programming problems. For example, the Singleton pattern ensures a class has only one instance throughout the application. This is useful for services like logging, where you want a single point of control. The pattern involves a private constructor and a static method to access the instance.
The factory design pattern in Java is a creational pattern that provides an interface for creating objects without specifying their concrete classes. It defines a method that returns different instances based on parameters. For example, a ShapeFactory might create Circle, Square, or Triangle objects based on a type parameter, hiding instantiation details from client code.
The singleton design pattern in Java ensures a class has exactly one instance and provides a global point to access it. It uses a private constructor to prevent external instantiation and a static method to return the single instance. This pattern is useful for classes like configuration managers or connection pools that should exist only once.
The builder design pattern in Java constructs complex objects step by step. It separates object construction from its representation. This pattern is ideal when an object has many parameters, some optional. Instead of multiple constructors, a builder class with fluent methods creates the object. For example, a DocumentBuilder builds documents with various attributes.
The adapter design pattern in Java allows classes with incompatible interfaces to work together. It converts one interface into another that clients expect. For example, an adapter might make a legacy TextFile class work with a new DocumentProcessor interface by implementing the interface and delegating to the adapted class.
Use the factory design pattern in Java when you need to create objects without exposing creation logic. It's useful when:
Use the singleton design pattern in Java when:
Use the builder design pattern in Java when:
To implement the factory design pattern in Java:
To implement the singleton design pattern in Java:
Design patterns in Java are grouped into three categories:
Take the Free Quiz on Java
Answer quick questions and assess your Java knowledge
Author|900 articles published
Previous
Next
Talk to our experts. We are available 7 days a week, 9 AM to 12 AM (midnight)
Indian Nationals
1800 210 2020
Foreign Nationals
+918068792934
1.The above statistics depend on various factors and individual results may vary. Past performance is no guarantee of future results.
2.The student assumes full responsibility for all expenses associated with visas, travel, & related costs. upGrad does not provide any a.