Understanding Java Design Patterns: Creative, Structural, Behavioral

Answered using GPT-4o-mini by Java Q&A Hub

Question:

How to understand creative vs structural vs behavioral in Java? Give examples

Answer:

In the context of Java (and software design in general), the terms "creative," "structural," and "behavioral" often refer to different categories of design patterns. These patterns help developers solve common problems in software design and architecture. Let's break down each category with definitions and examples.

1. Creative Patterns (Creational Patterns)

Definition: Creational patterns deal with object creation mechanisms, trying to create objects in a manner suitable to the situation. They abstract the instantiation process and help make the system independent of how its objects are created, composed, and represented.

Examples:

  • Singleton Pattern: Ensures a class has only one instance and provides a global point of access to it.

    public class Singleton {
        private static Singleton instance;
    
        private Singleton() {}
    
        public static Singleton getInstance() {
            if (instance == null) {
                instance = new Singleton();
            }
            return instance;
        }
    }
    
  • Factory Method Pattern: Defines an interface for creating an object but lets subclasses alter the type of objects that will be created.

    interface Product {
        void use();
    }
    
    class ConcreteProductA implements Product {
        public void use() {
            System.out.println("Using Product A");
        }
    }
    
    class ConcreteProductB implements Product {
        public void use() {
            System.out.println("Using Product B");
        }
    }
    
    abstract class Creator {
        public abstract Product factoryMethod();
    }
    
    class ConcreteCreatorA extends Creator {
        public Product factoryMethod() {
            return new ConcreteProductA();
        }
    }
    
    class ConcreteCreatorB extends Creator {
        public Product factoryMethod() {
            return new ConcreteProductB();
        }
    }
    

2. Structural Patterns

Definition: Structural patterns deal with object composition, creating relationships between objects to form larger structures. They help ensure that if one part of a system changes, the entire system doesn't need to change.

Examples:

  • Adapter Pattern: Allows incompatible interfaces to work together. It acts as a bridge between two incompatible interfaces.

    interface Target {
        void request();
    }
    
    class Adaptee {
        void specificRequest() {
            System.out.println("Specific request");
        }
    }
    
    class Adapter implements Target {
        private Adaptee adaptee;
    
        public Adapter(Adaptee adaptee) {
            this.adaptee = adaptee;
        }
    
        public void request() {
            adaptee.specificRequest();
        }
    }
    
  • Decorator Pattern: Allows behavior to be added to individual objects, either statically or dynamically, without affecting the behavior of other objects from the same class.

    interface Coffee {
        String getDescription();
        double cost();
    }
    
    class SimpleCoffee implements Coffee {
        public String getDescription() {
            return "Simple coffee";
        }
    
        public double cost() {
            return 1.00;
        }
    }
    
    class MilkDecorator implements Coffee {
        private Coffee coffee;
    
        public MilkDecorator(Coffee coffee) {
            this.coffee = coffee;
        }
    
        public String getDescription() {
            return coffee.getDescription() + ", milk";
        }
    
        public double cost() {
            return coffee.cost() + 0.50;
        }
    }
    

3. Behavioral Patterns

Definition: Behavioral patterns are concerned with algorithms and the assignment of responsibilities between objects. They help define how objects interact in a way that is flexible and easy to maintain.

Examples:

  • Observer Pattern: Defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

    interface Observer {
        void update(String message);
    }
    
    class ConcreteObserver implements Observer {
        private String name;
    
        public ConcreteObserver(String name) {
            this.name = name;
        }
    
        public void update(String message) {
            System.out.println(name + " received message: " + message);
        }
    }
    
    class Subject {
        private List<Observer> observers = new ArrayList<>();
    
        public void addObserver(Observer observer) {
            observers.add(observer);
        }
    
        public void notifyObservers(String message) {
            for (Observer observer : observers) {
                observer.update(message);
            }
        }
    }
    
  • Strategy Pattern: Defines a family of algorithms, encapsulates each one, and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.

    interface Strategy {
        int execute(int a, int b);
    }
    
    class AddStrategy implements Strategy {
        public int execute(int a, int b) {
            return a + b;
        }
    }
    
    class SubtractStrategy implements Strategy {
        public int execute(int a, int b) {
            return a - b;
        }
    }
    
    class Context {
        private Strategy strategy;
    
        public Context(Strategy strategy) {
            this.strategy = strategy;
        }
    
        public int executeStrategy(int a, int b) {
            return strategy.execute(a, b);
        }
    }
    

Summary

  • Creational Patterns focus on how objects are created.
  • Structural Patterns focus on how objects are composed to form larger structures.
  • Behavioral Patterns focus on how objects interact and communicate with each other.

Understanding these patterns can greatly enhance your ability to design flexible and maintainable software systems in Java or any other programming language.