Centrum wiedzy o technologiach i pracy w IT
wzorce projektowe java

Wzorce projektowe Java – pisz kod bardziej efektywnie

Ostatnia aktualizacja 5 kwietnia, 2024

Wzorce projektowe w Javie są istotnym elementem efektywnego programowania, pozwalającym na rozwiązanie typowych problemów projektowych w optymalny sposób. Ułatwiają one zarządzanie kodem, jego rozszerzanie i utrzymanie, zapewniając jednocześnie większą możliwość ponownego wykorzystania komponentów. Poniżej omawiamy najpopularniejsze z nich oraz wyjaśniamy ich działanie.

Nie udało się zapisać Twojej subskrypcji. Spróbuj ponownie.
Udało się! Widzimy się niebawem – newsletter wysyłamy w każdy wtorek

Otrzymuj za darmo unikalne poradniki, dane i wiedzę o pracy w IT – dostarczane co tydzień

Klikając “Zapisz mnie” wyrażasz zgodę na otrzymywanie e-maili od redakcji, a także ofert partnerów oraz akceptujesz naszą Politykę prywatności.

Wzorce projektowe Java: Singleton

Singleton to wzorzec projektowy, który gwarantuje, że klasa ma tylko jedną instancję i zapewnia globalny punkt dostępu do tej instancji. Jest on często używany w przypadkach, gdy potrzebna jest dokładnie jedna instancja obiektu, na przykład do zarządzania połączeniem z bazą danych.

Przykład kodu:

public class DatabaseConnector {
    private static DatabaseConnector instance;
    
    private DatabaseConnector() {
        // prywatny konstruktor uniemożliwia tworzenie instancji z zewnątrz
    }
    
    public static synchronized DatabaseConnector getInstance() {
        if (instance == null) {
            instance = new DatabaseConnector();
        }
        return instance;
    }
    
    public void connect() {
        // kod odpowiedzialny za nawiązanie połączenia z bazą danych
    }
}

W powyższym przykładzie klasa DatabaseConnector używa wzorca Singleton do zapewnienia, że można utworzyć tylko jedną jej instancję. Metoda getInstance zwraca tę instancję, tworząc ją, jeśli jeszcze nie istnieje. Dzięki temu, niezależnie od liczby wywołań metody getInstance, zawsze otrzymamy tę samą instancję DatabaseConnector.

Wzorce projektowe Java: Abstract Factory

Abstract Factory jest wzorcem kreacyjnym, który umożliwia tworzenie rodzin obiektów bez określania ich konkretnych klas. Ten wzorzec jest szczególnie użyteczny w sytuacji, gdy system ma być niezależny od sposobu tworzenia, komponowania i reprezentacji obiektów.

Przykład kodu:

interface GUIFactory {
    Button createButton();
    Checkbox createCheckbox();
}

class WinFactory implements GUIFactory {
    public Button createButton() {
        return new WinButton();
    }
    
    public Checkbox createCheckbox() {
        return new WinCheckbox();
    }
}

class MacFactory implements GUIFactory {
    public Button createButton() {
        return new MacButton();
    }
    
    public Checkbox createCheckbox() {
        return new MacCheckbox();
    }
}

interface Button {
    void paint();
}

interface Checkbox {
    void paint();
}

// Implementacje konkretnych komponentów pominięto dla zwięzłości

W przykładzie użyto wzorca Abstract Factory do tworzenia interfejsu użytkownika w sposób niezależny od systemu operacyjnego. GUIFactory definiuje interfejs dla fabryk, które produkują różne komponenty interfejsu (przyciski, pola wyboru), a konkretne implementacje tej fabryki (WinFactory, MacFactory) tworzą komponenty specyficzne dla danego systemu operacyjnego.

Wzorce projektowe Java: Dekorator

Dekorator to wzorzec strukturalny, który pozwala dynamicznie dodać nowe funkcje do obiektów bez zmiany ich struktury. Jest to przydatne, gdy chcemy rozszerzyć możliwości klas w sposób elastyczny i umożliwiający ponowne użycie.

Przykład kodu:

interface Coffee {
    double getCost();
    String getIngredients();
}

class SimpleCoffee implements Coffee {
    public double getCost() {
        return 1;
    }
    
    public String getIngredients() {
        return "Coffee";
    }
}

class WithMilk extends CoffeeDecorator {
    public WithMilk(Coffee coffee) {
        super(coffee);
    }
    
    public double getCost() {
        return super.getCost() + 0.5;
    }
    public String getIngredients() {
        return super.getIngredients() + ", Milk";
    }
}

abstract class CoffeeDecorator implements Coffee {
    protected final Coffee decoratedCoffee;
    
    public CoffeeDecorator(Coffee coffee) {
        this.decoratedCoffee = coffee;
    }
    
    public double getCost() {
        return decoratedCoffee.getCost();
    }
    
    public String getIngredients() {
        return decoratedCoffee.getIngredients();
    }
}

W tym przykładzie Coffee jest podstawowym interfejsem dla różnych rodzajów kawy, a SimpleCoffee jest prostą kawą bez dodatków. CoffeeDecorator jest abstrakcyjną klasą dekorującą, która implementuje interfejs Coffee i pozwala na dodawanie nowych składników (takich jak mleko w WithMilk) do kawy. Dzięki temu można tworzyć złożone kombinacje składników, zachowując przy tym przejrzystość i elastyczność kodu.

Dalsza część tekstu znajduje się pod materiałem wideo:

W jakich sytuacjach warto wykorzystać wzorce projektowe?

Wzorce projektowe stanowią sprawdzone rozwiązania dla często występujących problemów projektowych i powinny być wykorzystywane w określonych sytuacjach:

  • Zarządzanie zmianami i rozszerzalnością. Gdy oczekuje się, że projekt będzie się rozwijał i zmieniał, wzorce projektowe ułatwiają dodawanie nowych funkcji bez zakłócania istniejącej struktury kodu.
  • Unikanie powtarzalności kodu. Kiedy podobne problemy pojawiają się w różnych miejscach aplikacji, wzorce projektowe pomagają unikać duplikacji kodu poprzez ponowne wykorzystanie rozwiązań.
  • Separacja obowiązków. Gdy istnieje potrzeba wyraźnego oddzielenia różnych aspektów aplikacji, wzorce projektowe, takie jak MVC (Model-View-Controller), ułatwiają podział odpowiedzialności.
  • Komunikacja między obiektami. W sytuacjach wymagających skomplikowanej komunikacji między obiektami, wzorce projektowe takie jak Obserwator, ułatwiają ich efektywne włączanie i zarządzanie zdarzeniami.
  • Zarządzanie zasobami. Kiedy zarządzanie zasobami, np. połączeniami z bazą danych lub plikami, wymaga szczególnej uwagi, wzorzec Singleton zapewnia kontrolowaną instancję zarządzająca dostępem do zasobów.
  • Optymalizacja operacji kreacyjnych. Gdy tworzenie obiektów jest złożone lub kosztowne w kontekście zasobów, wzorce kreacyjne, takie jak Budowniczy (Builder) lub Prototyp, oferują efektywne strategie ich inicjalizacji.
  • Adaptacja interfejsów. Kiedy konieczne jest dopasowanie niekompatybilnych interfejsów, wzorzec Adapter pozwala na współpracę klas, które inaczej nie mogłyby ze sobą działać.
  • Uproszczenie złożonych struktur. W przypadku skomplikowanych struktur danych lub algorytmów, wzorce strukturalne, takie jak Kompozyt, pomagają zarządzać złożonością poprzez uproszczone interfejsy.

Dziękujemy, że przeczytałaś/eś nasz artykuł. Obserwuj EnterTheCode.pl w Wiadomościach Google, aby być na bieżąco.

Czytaj także:

Java map – podstawy, przykłady i najlepsze praktyki

Error Java error release version 5 not supported – rozwiązanie

Total
0
Shares
_podobne artykuły