Design pattern are proven, reusable solutions to recurring problems in software design. They provide structured approaches that help developers build scalable, maintainable systems — applicable across domains like DDD or enterprise applications.
Core Patterns Covered
- Strategy Pattern
- Factory Pattern
- Singleton Pattern
- Proxy Pattern
- Factory Method Pattern
- Observer Pattern
- Template Method Pattern
- Adapter Pattern
Scenario-Based Implementation: Discount Pricing System
A retail system applies different discount rules based on purchase amount:
- ≥ 2000 → 20% off
- 500–1999 → 10% off
- < 500 → 5% off
Strategy Pattern Refactored
public interface DiscountPolicy {
String getIdentifier();
BigDecimal applyDiscount(BigDecimal originalPrice);
}
@Component
public class PremiumDiscount implements DiscountPolicy {
@Override
public String getIdentifier() { return "PREMIUM"; }
@Override
public BigDecimal applyDiscount(BigDecimal price) {
return price.multiply(BigDecimal.valueOf(0.8));
}
}
@Component
public class StandardDiscount implements DiscountPolicy {
@Override
public String getIdentifier() { return "STANDARD"; }
@Override
public BigDecimal applyDiscount(BigDecimal price) {
return price.multiply(BigDecimal.valueOf(0.9));
}
}
@Component
public class BasicDiscount implements DiscountPolicy {
@Override
public String getIdentifier() { return "BASIC"; }
@Override
public BigDecimal applyDiscount(BigDecimal price) {
return price.multiply(BigDecimal.valueOf(0.95));
}
}
Auto-wired strategy dispatcher using Spring:
@Configuration
public class DiscountConfig {
@Bean
public Function<String, DiscountPolicy> discountRouter(List<DiscountPolicy> policies) {
return policies.stream()
.collect(Collectors.toMap(
DiscountPolicy::getIdentifier,
Function.identity()
))::get;
}
}
@RestController
@RequestMapping("/pricing")
public class PricingController {
private final Function<String, DiscountPolicy> discountRouter;
public PricingController(Function<String, DiscountPolicy> router) {
this.discountRouter = router;
}
@GetMapping("/calculate")
public BigDecimal calculate(@RequestParam BigDecimal amount, @RequestParam String tier) {
DiscountPolicy policy = discountRouter.apply(tier);
return policy.applyDiscount(amount);
}
}
Payment Gateway Factory (Simplified)
public interface PaymentProcessor {
boolean process(PaymentRequest request);
}
public class AlipayProcessor implements PaymentProcessor {
@Override
public boolean process(PaymentRequest req) {
System.out.println("Processing via Alipay...");
return true;
}
}
public class WechatPayProcessor implements PaymentProcessor {
@Override
public boolean process(PaymentRequest req) {
System.out.println("Processing via WeChat Pay...");
return true;
}
}
@Component
public class PaymentFactory {
private final Map<String, PaymentProcessor> processors = new HashMap<>();
@PostConstruct
public void init() {
processors.put("ALIPAY", new AlipayProcessor());
processors.put("WECHAT", new WechatPayProcessor());
}
public PaymentProcessor getProcessor(String method) {
if (!processors.containsKey(method)) {
throw new IllegalArgumentException("Unsupported payment method: " + method);
}
return processors.get(method);
}
}
Thread-Safe Singlteon (Static Inner Class)
public class ConfigurationManager {
private ConfigurationManager() {}
private static class Holder {
static final ConfigurationManager INSTANCE = new ConfigurationManager();
}
public static ConfigurationManager getInstance() {
return Holder.INSTANCE;
}
}
Proxy Pattern: Property Rental
public interface RentalService {
void leaseProperty();
}
public class Landlord implements RentalService {
@Override
public void leaseProperty() {
System.out.println("Property leased directly by owner.");
}
}
public class AgencyProxy implements RentalService {
private final Landlord landlord = new Landlord();
@Override
public void leaseProperty() {
System.out.println("Agency collects fee and facilitates lease...");
landlord.leaseProperty();
}
}
Factory Method Pattern: Network Service Router
public interface NetworkHandler {
NetworkResponse handle(NetworkRequest request);
}
@Service
public class MobileNetworkHandler implements NetworkHandler {
@Override
public NetworkResponse handle(NetworkRequest req) {
return new NetworkResponse("Mobile");
}
}
@Service
public class FiberNetworkHandler implements NetworkHandler {
@Override
public NetworkResponse handle(NetworkRequest req) {
return new NetworkResponse("Fiber");
}
}
@Service
public class NetworkFactory {
private final Map<String, NetworkHandler> handlers;
public NetworkFactory(List<NetworkHandler> handlerList) {
this.handlers = handlerList.stream()
.collect(Collectors.toMap(h -> h.getClass().getSimpleName().replace("Handler", ""), h -> h));
}
public NetworkHandler getHandler(String type) {
return handlers.get(type.toUpperCase());
}
}
Observer Pattern: Weather Monitoring
interface WeatherSubject {
void register(WeatherObserver observer);
void notifyObservers();
}
interface WeatherObserver {
void update(float temp, float humidity);
}
class WeatherStation implements WeatherSubject {
private final List<WeatherObserver> observers = new ArrayList<>();
private float temperature, humidity;
@Override
public void register(WeatherObserver o) { observers.add(o); }
@Override
public void notifyObservers() {
for (WeatherObserver obs : observers) {
obs.update(temperature, humidity);
}
}
public void setReadings(float temp, float hum) {
this.temperature = temp;
this.humidity = hum;
notifyObservers();
}
}
class DisplayBoard implements WeatherObserver {
@Override
public void update(float temp, float humidity) {
System.out.printf("Current: %.1f°C, Humidity: %.0f%%%n", temp, humidity);
}
}
Template Method: House Construction Blueprint
abstract class ConstructionTemplate {
public final void buildStructure() {
layFoundation();
erectFrame();
installWalls();
mountWindows();
System.out.println("Construction completed.");
}
private void layFoundation() {
System.out.println("Pouring concrete foundation...");
}
protected abstract void erectFrame();
protected abstract void installWalls();
private void mountWindows() {
System.out.println("Installing double-glazed windows.");
}
}
class TimberFrameHouse extends ConstructionTemplate {
@Override protected void erectFrame() { System.out.println("Assembling timber frame..."); }
@Override protected void installWalls() { System.out.println("Mounting wooden panel walls..."); }
}
class SteelFrameHouse extends ConstructionTemplate {
@Override protected void erectFrame() { System.out.println("Welding steel beams..."); }
@Override protected void installWalls() { System.out.println("Attaching metal cladding..."); }
}
Adapter Pattern: Network Interface Converter
class EthernetCable {
public void transmitData() {
System.out.println("Transmitting via Ethernet cable.");
}
}
interface UsbPort {
void sendData();
}
class EthernetToUsbAdapter implements UsbPort {
private final EthernetCable cable = new EthernetCable();
@Override
public void sendData() {
cable.transmitData();
}
}
class Laptop {
public void connect(UsbPort port) {
port.sendData();
}
}