BeSmartAnd.Pro

Wzorce projektowe są fundamentem dobrze zaprojektowanego oprogramowania. Pomagają w rozwiązywaniu powszechnych problemów w sposób uporządkowany i efektywny. W tym artykule omówimy trzy kolejne popularne wzorce projektowe: Dekorator (Decorator), Strategia (Strategy) oraz Adapter (Adapter), a także zaprezentujemy ich implementacje w PHP.

 

1. Dekorator (Decorator)

Wzorzec Dekoratora pozwala na dynamiczne dodawanie nowych funkcji do obiektów poprzez "owijanie" ich w dodatkowe klasy dekorujące. Jest to elastyczny sposób rozszerzania funkcjonalności obiektów bez modyfikowania ich kodu.

interface Coffee {
    public function getCost();

    public function getDescription();
}



class SimpleCoffee implements Coffee {
    public function getCost() {
        return 5;
    }


    public function getDescription() {
        return "Simple coffee";
    }
}


class MilkDecorator implements Coffee {
    protected $coffee;

    public function __construct(Coffee $coffee) {
        $this->coffee = $coffee;
    }

    public function getCost() {
        return $this->coffee->getCost() + 2;
    }

    public function getDescription() {
        return $this->coffee->getDescription() . ", milk";
    }
}

class SugarDecorator implements Coffee {
    protected $coffee;

    public function __construct(Coffee $coffee) {
        $this->coffee = $coffee;
    }

    public function getCost() {
        return $this->coffee->getCost() + 1;
    }

    public function getDescription() {
        return $this->coffee->getDescription() . ", sugar";
    }
}


// Użycie wzorca Dekoratora

$coffee = new SimpleCoffee();

echo $coffee->getDescription() . " costs $" . $coffee->getCost() . "\n";


$milkCoffee = new MilkDecorator($coffee);

echo $milkCoffee->getDescription() . " costs $" . $milkCoffee->getCost() . "\n";


$sugarMilkCoffee = new SugarDecorator($milkCoffee);

echo $sugarMilkCoffee->getDescription() . " costs $" . $sugarMilkCoffee->getCost() . "\n";

 

W powyższym przykładzie `MilkDecorator` i `SugarDecorator` dodają nowe funkcje do obiektu `SimpleCoffee` bez zmiany jego kodu. Dzięki temu możemy dynamicznie komponować różne dodatki do kawy.

2. Strategia (Strategy)

Wzorzec Strategii pozwala na definiowanie rodzin algorytmów, umieszczanie ich w osobnych klasach i łatwe zamienianie między sobą. Dzięki temu wzorcowi możemy zmieniać sposób działania obiektu w trakcie działania programu.

interface PaymentStrategy {
    public function pay($amount);
}


class CreditCardPayment implements PaymentStrategy {
    public function pay($amount) {
        echo "Paying $" . $amount . " using Credit Card.\n";
    }
}


class PayPalPayment implements PaymentStrategy {
    public function pay($amount) {
        echo "Paying $" . $amount . " using PayPal.\n";
    }
}


class ShoppingCart {
    private $paymentStrategy;

    public function __construct(PaymentStrategy $paymentStrategy) {
        $this->paymentStrategy = $paymentStrategy;
    }

    public function checkout($amount) {
        $this->paymentStrategy->pay($amount);
    }
}


// Użycie wzorca Strategii
$cart = new ShoppingCart(new CreditCardPayment());

$cart->checkout(100);


$cart = new ShoppingCart(new PayPalPayment());

$cart->checkout(200);

W powyższym przykładzie wzorzec Strategii pozwala na łatwą zmianę sposobu płatności w koszyku zakupowym poprzez przekazanie odpowiedniej strategii do klasy `ShoppingCart`.

3. Adapter (Adapter)

Wzorzec Adapter pozwala na dopasowanie interfejsu istniejącej klasy do oczekiwanego przez klienta interfejsu. Dzięki temu możemy używać klasy z niekompatybilnym interfejsem bez modyfikowania jej kodu.

interface Book {
    public function turnPage();

    public function open();
}


class PaperBook implements Book {
    public function turnPage() {
        echo "Turning page of the paper book.\n";
    }

    public function open() {
        echo "Opening the paper book.\n";
    }
}


interface eBook {
    public function pressNext();

    public function unlock();
}


class Kindle implements eBook {
    public function pressNext() {
        echo "Pressing next on the Kindle.\n";
    }

    public function unlock() {
        echo "Unlocking the Kindle.\n";
    }
}


class eBookAdapter implements Book {
    private $eBook;

    public function __construct(eBook $eBook) {
        $this->eBook = $eBook;
    }

    public function turnPage() {
        $this->eBook->pressNext();
    }

    public function open() {
        $this->eBook->unlock();
    }
}

// Użycie wzorca Adaptera

$kindle = new Kindle();

$book = new eBookAdapter($kindle);

$book->open();

$book->turnPage();

W powyższym przykładzie `eBookAdapter` dostosowuje interfejs `Kindle` do interfejsu `Book`, umożliwiając korzystanie z Kindle jako zwykłej książki.

Podsumowanie

Wzorce projektowe, takie jak Dekorator, Strategia i Adapter, są kluczowymi narzędziami w arsenale każdego programisty. Umożliwiają tworzenie elastycznego, łatwego do utrzymania i rozszerzalnego kodu. Implementacja tych wzorców w PHP pokazuje, jak można efektywnie rozwiązywać typowe problemy projektowe i tworzyć solidne aplikacje.