Sobes.tech
Middle+

What tasks have you encountered when using design patterns?

sobes.tech AI

Answer from AI

Regarding improvement tasks:

  1. Maintainability and extensibility of code: Patterns made the code more readable and structured, simplifying changes and adding new functionality.
  2. Elimination of duplication: Factory methods or abstract factories helped centralize object creation.
  3. Solving typical problems:
    • Object creation (Factory Method, Abstract Factory, Builder, Prototype, Singleton).
    • Organizing interaction between objects (Strategy, Observer, Command, Mediator).
    • Structuring classes and objects (Adapter, Decorator, Composite, Facade, Proxy).
  4. Increasing flexibility: Using Strategy to select algorithms depending on the context.
  5. Managing object lifecycle: Singleton to ensure a single instance of a class.
  6. Separation of concerns: Applying MVC (Model-View-Controller) or similar patterns to separate logic.

For example, I often used the Builder pattern to create complex objects with many optional parameters, which made the initialization code more readable and safe, avoiding issues with numerous overloaded constructors.

// Example of using Builder
public class User {
    private final String firstName;
    private final String lastName;
    private final int age;
    private final String phone;
    private final String address;

    // Private constructor
    private User(Builder builder) {
        this.firstName = builder.firstName;
        this.lastName = builder.lastName;
        this.age = builder.age;
        this.phone = builder.phone;
        this.address = builder.address;
    }

    // Getters

    public static class Builder {
        private final String firstName;
        private final String lastName;
        private int age = 0; // Default values
        private String phone = "";
        private String address = "";

        public Builder(String firstName, String lastName) {
            this.firstName = firstName;
            this.lastName = lastName;
        }

        public Builder age(int age) {
            this.age = age;
            return this;
        }

        public Builder phone(String phone) {
            this.phone = phone;
            return this;
        }

        public Builder address(String address) {
            this.address = address;
            return this;
        }

        public User build() {
            return new User(this);
        }
    }

    // Usage example
    public static void main(String[] args) {
        User user = new User.Builder("John", "Doe")
            .age(30)
            .phone("123-456-7890")
            .build();
    }
}

Also, Strategy is used to implement various sorting or data processing algorithms, allowing easy switching of the used algorithm without changing client code.

// Strategy interface
interface SortingStrategy {
    void sort(int[] array);
}

// Bubble sort strategy
class BubbleSort implements SortingStrategy {
    @Override
    public void sort(int[] array) {
        // Bubble sort logic
        System.out.println("Sorting using Bubble Sort");
    }
}

// Quick sort strategy
class QuickSort implements SortingStrategy {
    @Override
    public void sort(int[] array) {
        // Quick sort logic
        System.out.println("Sorting using Quick Sort");
    }
}

// Context
class Sorter {
    private SortingStrategy strategy;

    public void setStrategy(SortingStrategy strategy) {
        this.strategy = strategy;
    }

    public void performSort(int[] array) {
        if (strategy != null) {
            strategy.sort(array);
        } else {
            System.out.println("No sorting strategy set.");
        }
    }

    // Usage example
    public static void main(String[] args) {
        Sorter sorter = new Sorter();
        int[] data = {5, 2, 8, 1, 9};

        sorter.setStrategy(new BubbleSort());
        sorter.performSort(data);

        sorter.setStrategy(new QuickSort());
        sorter.performSort(data);
    }
}