A design pattern in Java is a reusable solution to a commonly occurring problem in software design. It is a proven and tested way of solving a particular type of problem in software development. These patterns can be applied to different software systems and can help improve the quality of code, reduce development time and effort, and make the code more maintainable and extensible.
There are several design patterns in Java, which can be broadly classified into three categories: creational, structural, and behavioral patterns.
Creational patterns: These patterns focus on object creation mechanisms, trying to create objects in a manner suitable to the situation. The creational patterns include Singleton, Factory Method, Abstract Factory, Builder, and Prototype.
//Singleton design pattern
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
//Factory method design pattern
public interface Vehicle {
void drive();
}
public class Car implements Vehicle {
@Override
public void drive() {
System.out.println("Driving a car");
}
}
public class Motorcycle implements Vehicle {
@Override
public void drive() {
System.out.println("Driving a motorcycle");
}
}
public class VehicleFactory {
public static Vehicle createVehicle(String type) {
switch (type) {
case "car":
return new Car();
case "motorcycle":
return new Motorcycle();
default:
throw new IllegalArgumentException("Invalid vehicle type: " + type);
}
}
}
Structural patterns: These patterns focus on object composition and help in forming large object structures. The structural patterns include Adapter, Bridge, Composite, Decorator, Facade, Flyweight, and Proxy.
//Decorator design pattern
public interface Car {
String getDescription();
double getCost();
}
public class BasicCar implements Car {
@Override
public String getDescription() {
return "Basic car";
}
@Override
public double getCost() {
return 10000.0;
}
}
public abstract class CarDecorator implements Car {
protected Car car;
public CarDecorator(Car car) {
this.car = car;
}
@Override
public String getDescription() {
return car.getDescription();
}
@Override
public double getCost() {
return car.getCost();
}
}
public class SportsPackage extends CarDecorator {
public SportsPackage(Car car) {
super(car);
}
@Override
public String getDescription() {
return car.getDescription() + ", sports package";
}
}