Symfony PHP: Kompleksowy przewodnik po frameworku
Symfony to jedno z najpopularniejszych narzędzi w świecie PHP, szeroko stosowane przez programist&oa...
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.
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.
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`.
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.
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.