Fundamentals 21 min read

Mastering Design Patterns: Strategy, Factory, Singleton, Proxy, Observer, Template & Adapter in Java

This article provides a comprehensive, code‑first guide to the most common design patterns—including Strategy, Simple Factory, Singleton, Proxy, Factory Method, Observer, Template Method and Adapter—explaining their concepts, real‑world use cases, and complete Java implementations with Spring Boot integration.

IT Architects Alliance
IT Architects Alliance
IT Architects Alliance
Mastering Design Patterns: Strategy, Factory, Singleton, Proxy, Observer, Template & Adapter in Java

Introduction

Design patterns are reusable solutions to recurring software design problems. When a pattern fits the problem context, it can be applied across domains such as Domain‑Driven Design (DDD) or classic object‑oriented design.

Common Design Patterns

Strategy

Factory

Singleton

Proxy

Factory Method

Observer

Template Method

Adapter

1. Strategy Pattern

Scenario: a retail promotion applies different discount rates based on purchase amount. The Strategy interface defines String strategy() (identifier) and void algorithm() (business logic). Three concrete strategies (A, B, C) implement the interface, each printing its own processing message.

Strategy enumeration ( StrategySelector) maps a numeric code to a string identifier. StrategyRunner holds a List<Strategy> and builds a Map<String, Strategy> for fast lookup. The execute(String strategy) method retrieves the appropriate Strategy and runs its algorithm().

Spring Boot configuration registers all Strategy beans automatically. A controller exposes an endpoint /designPatterns/algorithm?strategy=... that delegates to strategyRunner.execute(), producing console output such as process with strategyA....

2. Simple Factory Pattern

Scenario: a payment system supports Alipay, WeChat Pay, and UnionPay. An IPayment interface defines Boolean pay(PaymentBody). Concrete implementations ( AliPay, WechatPay, UnionPay) print the payment channel and return TRUE.

The PaymentFactory uses EnumUtil to map a payment type to the fully‑qualified class name and creates the strategy via reflection. PayStrategyEnum stores the mapping.

A PaymentContext receives an IPayment instance and forwards the pay call. PaymentStrategyHandler validates the type, obtains the strategy from the factory, builds a context, and executes the payment. A REST controller provides a /designPatterns/pay POST endpoint.

3. Singleton Pattern

Implemented with a static inner holder class ( SingletonInstance) that contains a final INSTANCE. The public getInstance() method returns the holder’s instance, guaranteeing lazy, thread‑safe initialization.

4. Proxy Pattern

Real‑world analogy: a landlord delegates rental to a real‑estate agent. The Subject interface declares void rentHouse(). HouseOwner implements the actual rental logic. HouseProxy holds a HouseOwner reference and adds a proxy fee before delegating the call. A controller invokes the proxy via a REST endpoint.

5. Factory Method Pattern

Defines an abstract NetworkConfigFactoryService with

NetworkConfigCrudService getSpecificService(String productType)

. The concrete NetworkConfigFactoryServiceImpl injects four service implementations (A‑D) and selects one via a switch. Each service implements NetworkConfigCrudService and returns a NetworkConfigVO. A controller demonstrates fetching a specific service and returning the result.

6. Observer Pattern

Illustrated with a weather‑station example. Subject defines registration, removal, and notification methods. Observer defines update(float temp, float humidity, float pressure). WeatherData implements Subject, stores observers, and notifies them when measurements change. CurrentConditionDisplay implements both Observer and Display, updating its state and printing a message. A variant uses Java’s built‑in Observable and Observer interfaces.

7. Template Method Pattern

Abstract class HouseTemplate defines the final buildHouse() algorithm: build foundation, pillars, walls, windows, then print success. Subclasses must implement buildPillars() and buildWalls(). Concrete subclasses ( WoodenHouse, GlassHouse, ConcreteHouse) provide specific pillar and wall implementations. A client creates each house type and calls buildHouse(), producing ordered output.

8. Adapter Pattern

Class adapter example: an Adaptee (network cable) provides request(). Target interface NetToUsb declares handleRequest(). Adapter extends Adaptee and implements NetToUsb, delegating handleRequest() to super.request(). A Computer class expects a NetToUsb and calls net(adapter). The main method wires everything together.

Conclusion

Design patterns encapsulate proven object‑oriented solutions. Understanding their intent, structure, and Java implementation—especially when combined with Spring Boot’s dependency injection—helps developers write flexible, maintainable code.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Design PatternsJavaProxyTemplate MethodSingletonAdapterstrategyFactoryObserver
IT Architects Alliance
Written by

IT Architects Alliance

Discussion and exchange on system, internet, large‑scale distributed, high‑availability, and high‑performance architectures, as well as big data, machine learning, AI, and architecture adjustments with internet technologies. Includes real‑world large‑scale architecture case studies. Open to architects who have ideas and enjoy sharing.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.