-
Notifications
You must be signed in to change notification settings - Fork 0
Java Design Patterns Wiki
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.
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.
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.
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.
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.
Definition: Depend on abstractions, not on concrete implementations.
Best Practice: Use DIP to decouple high-level modules from low-level modules.
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.
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.
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.
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.
Usage: To allow incompatible interfaces to work together.
Best Practice: Use when integrating legacy code or third-party libraries.
Usage: To decouple an abstraction from its implementation.
Best Practice: Use when both abstraction and implementation need to vary independently.
Usage: To treat individual objects and compositions of objects uniformly.
Best Practice: Use for hierarchical structures like file systems or UI components.
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.
Usage: To provide a unified interface to a subsystem.
Best Practice: Use to simplify complex systems.
Usage: To minimize memory usage by sharing objects.
- Flyweight-1, Flyweight-2, Flyweight-3: Examples of formatted text optimizations.
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.
Usage: To pass requests along a chain of handlers.
- Command-Query COR: For separating requests and queries.
- Method COR: For method chaining in processing.
Usage: To encapsulate requests as objects.
Usage: To define a grammar and interpret sentences.
- Interpreter-1, Interpreter-2: Examples for parsing expressions.
Usage: To traverse a collection without exposing its structure.
- Array-Backed-Drop: Example with array-backed collections.
Usage: To encapsulate communication between objects.
- Event Broker: For event-driven communication.
Usage: To capture and restore an object’s state.
Usage: To provide a default implementation for absent objects.
Usage: To notify multiple objects about state changes.
- Observer-Event: For event-driven notifications.
Usage: To change behavior based on state.
- State-Handmade: Manual state management.
- State-Spring: Integration with Spring.
Usage: To define a family of algorithms.
- Dynamic Strategy: For runtime strategy selection.
- Static Strategy: For compile-time strategy selection.
Usage: To define the skeleton of an algorithm.
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.
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!