Skip to content

Java Design Patterns Wiki

ozgen mehmet edited this page Jan 10, 2025 · 2 revisions

Welcome to the Java-Design-Patterns project wiki! This repository contains examples of design patterns and SOLID principles implemented in Java. The goal of this project is to provide clear, practical examples of how these patterns and principles can be applied in software development.

SOLID Principles

Single Responsibility Principle (SRP)

Definition: A class should have only one reason to change.

Best Practice: Use SRP when a class starts accumulating multiple responsibilities, such as managing database operations, UI logic, or business rules.

Open/Closed Principle (OCP)

Definition: Software entities should be open for extension but closed for modification.

Best Practice: Use OCP when adding new functionality. Avoid modifying existing classes by using abstraction and interfaces.

Liskov Substitution Principle (LSP)

Definition: Objects of a superclass should be replaceable with objects of its subclasses without altering the correctness of the program.

Best Practice: Ensure subclasses adhere to the behavior of their base classes.

Interface Segregation Principle (ISP)

Definition: A client should not be forced to depend on interfaces it does not use.

Best Practice: Use ISP when designing interfaces to keep them focused and cohesive.

Dependency Inversion Principle (DIP)

Definition: Depend on abstractions, not on concrete implementations.

Best Practice: Use DIP to decouple high-level modules from low-level modules.


Design Patterns

Creational Patterns

Builder Design Pattern

Usage: To construct complex objects step by step.

  • Facet Builder: When you want to divide the object creation process into multiple stages.
  • Fluent Builder: For readable and chainable object creation.

Factories Design Pattern

Usage: To create objects without exposing the instantiation logic.

  • Abstract Factories: When the system needs families of related objects.
  • Basic Factories: For simple, centralized object creation.
  • Method Factories: When creation logic depends on input parameters.

Prototype Design Pattern

Usage: To create new objects by copying existing ones.

  • Basic Prototype: For straightforward cloning.
  • Serialize Prototype: To create deep copies using serialization.
  • Copy-Constructor Prototype: For manual, controlled copying.

Singleton Design Pattern

Usage: To ensure a class has only one instance.

  • Basic Singleton: For simple single-instance enforcement.
  • Enum-Based Singleton: For thread-safe, serialization-safe singletons.
  • Inner-Static Singleton: For lazy-loaded singletons.
  • Lazy Singleton: To delay initialization until the first use.
  • Mutation Singleton: For situations requiring controlled instance updates.
  • Testability Singleton: To create test-friendly singleton implementations.

Structural Patterns

Adapter Design Pattern

Usage: To allow incompatible interfaces to work together.

Best Practice: Use when integrating legacy code or third-party libraries.

Bridge Design Pattern

Usage: To decouple an abstraction from its implementation.

Best Practice: Use when both abstraction and implementation need to vary independently.

Composite Design Pattern

Usage: To treat individual objects and compositions of objects uniformly.

Best Practice: Use for hierarchical structures like file systems or UI components.

Decorator Design Pattern

Usage: To dynamically add or modify the behavior of an object.

  • Adapter Decorator: When combining adapter and decorator behaviors.
  • Dynamic Decorator: For runtime modifications.
  • String Decorator: For enhancing string operations.

Facade Design Pattern

Usage: To provide a unified interface to a subsystem.

Best Practice: Use to simplify complex systems.

Flyweight Design Pattern

Usage: To minimize memory usage by sharing objects.

  • Flyweight-1, Flyweight-2, Flyweight-3: Examples of formatted text optimizations.

Proxy Design Pattern

Usage: To control access to objects.

  • Dynamic Proxy: For runtime proxy generation.
  • Property Proxy: To wrap and manage object properties.
  • Protection Proxy: To enforce access control.

Behavioral Patterns

Chain of Responsibility Design Pattern

Usage: To pass requests along a chain of handlers.

  • Command-Query COR: For separating requests and queries.
  • Method COR: For method chaining in processing.

Command Design Pattern

Usage: To encapsulate requests as objects.

Interpreter Design Pattern

Usage: To define a grammar and interpret sentences.

  • Interpreter-1, Interpreter-2: Examples for parsing expressions.

Iterator Design Pattern

Usage: To traverse a collection without exposing its structure.

  • Array-Backed-Drop: Example with array-backed collections.

Mediator Design Pattern

Usage: To encapsulate communication between objects.

  • Event Broker: For event-driven communication.

Memento Design Pattern

Usage: To capture and restore an object’s state.

Null Object Design Pattern

Usage: To provide a default implementation for absent objects.

Observer Design Pattern

Usage: To notify multiple objects about state changes.

  • Observer-Event: For event-driven notifications.

State Design Pattern

Usage: To change behavior based on state.

  • State-Handmade: Manual state management.
  • State-Spring: Integration with Spring.

Strategy Design Pattern

Usage: To define a family of algorithms.

  • Dynamic Strategy: For runtime strategy selection.
  • Static Strategy: For compile-time strategy selection.

Template Method Design Pattern

Usage: To define the skeleton of an algorithm.

Visitor Design Pattern

Usage: To separate algorithms from the objects they operate on.

  • Intrusive Visitor: For tightly coupled implementations.
  • Reflective Visitor: For reflection-based operations.
  • Classic Visitor: For traditional implementations.
  • Acyclic Visitor: To reduce coupling.

Contribution Guidelines

Feel free to contribute to this project by adding more examples, improving existing ones, or suggesting best practices. Open a pull request with your changes!