Decorator Design Pattern trong PHP
NỘI DUNG BÀI VIẾT
Decorator Pattern là một trong các Design Pattern được giới thiệu bởi Gang of Four, đây là một pattern có tuần suất sử dụng trung bình (3/5 với thang điểm tần suất sử dụng 5). Decorator thuộc về nhóm Structural Design Pattern là các mẫu lập trình liên quan đến cấu trúc, kết cấu các đối tượng. Decorator pattern được sử dụng khi:
The new features are added by creating new classes that belong to the same type as the existing classes. Tính năng mới được thêm vào bằng cách tạo class mới có cùng dạng với class đang có.
Decorator Pattern UML

Mẫu Decorator bao gồm một abstract class được implement từ interface khung của các class cơ bản, từ đó nó sẽ mở rộng ra các class có thêm các tính năng. ## Ví dụ thực tế áp dụng Decorator Pattern
Chúng ta cùng đến với ví dụ về những chiếc xế hộp, một interface tạo ra khung cho các class:
interface Car {
public function cost();
function description();
}
Code language: PHP (php)
Nhà máy sản xuất ra rất nhiều loại xe khác nhau từ interface Car như SUV, sedan, luxury… Ví dụ class SUV được implement từ interface Car:
class Suv implements Car {
function cost() {
return 30000;
}
function description () {
return "Xe SUV";
}
}
Code language: PHP (php)
Vấn đề là khách hàng muốn thêm các tùy chọn vào xế hộp như cửa sổ trời, lốp công nghệ cao, cánh gió, ghế bọc da, gắn định vị GPS… Chúng ta không muốn thay đổi class hiện tại để thêm các tùy chọn của khách hàng vào, giải pháp nào cho vấn đề này? Decorator pattern giải quyết vấn đề này, áp dụng mẫu này cho phép bạn thêm tính năng vào các class cơ bản được implement từ một interface.
Một abstract class được sử dụng, nó cũng implement từ interface trên và nó mở rộng tính năng hơn class cơ bản. Ok, trong trường hợp xế hộp ở trên chúng ta tạo ra một abstract class CarFeature implement interface Car:
abstract class CarFeature implements Car {
protected $car;
function __construct(Car $car) {
$this->car = $car;
}
abstract function cost();
abstract function description();
}
Code language: PHP (php)
abstract class CarFeature có hai phương thức abstract cần được định nghĩa trong các lớp con mở rộng từ lớp này. Ví dụ, xe cần có cửa trời sẽ là một class được mở rộng từ CarFeature:
class SunRoof extends CarFeature {
function cost () {
return $this->car->cost() + 1500;
}
function description() {
return $this->car->description() . ", cửa sổ trời";
}
}
Code language: PHP (php)
Tương tự với xế hộp cần thêm tùy chọn ghế bọc da:
class LeatherSeats extends CarFeature {
function cost () {
return $this->car->cost() + 1000;
}
function description() {
return $this->car->description() . ", ghế bọc da";
}
}
Code language: PHP (php)
Tùy chọn bộ định vị toàn cầu GPS:
class GPSNavigation extends CarFeature {
function cost () {
return $this->car->cost() + 800;
}
function description() {
return $this->car->description() . ", định vị toàn cầu GPS";
}
}
Code language: PHP (php)
Chúng ta thử tạo ra các loại xe khác nhau xem tính năng của chúng như thế nào:
// Tạo ra một xe cơ bản chưa có tùy chọn
$basicCar = new Suv();
// Truyền đối tượng này vào class mới thêm tùy chọn
$carWithSunRoof = new SunRoof($basicCar);
// Kiểm tra các tính năng trên xe đã có tùy chọn
echo $carWithSunRoof -> description();
echo " giá " . $carWithSunRoof -> cost();
Code language: PHP (php)
Kết quả như sau: Xe SUV, cửa sổ trời giá 31500 Nếu chúng ta muốn chiếc xe cơ bản có thêm nhiều các tùy chọn hơn như cả cửa sổ trời và lốp công nghệ cao, có thể truyền các class vào class cần mở rộng nhiều lần:
// 1. Tạo một xe cơ bản
$basicCar = new Suv();
// 2. Thêm tùy chọn cửa sổ trời
$carWithSunRoof = new SunRoof($basicCar);
// 3. Thêm tùy chọn ghế bọc da
$carWithSunRoofAndLeatherSeats = new LeatherSeats($carWithSunRoof);
// 4. Thêm tùy chọn GPS
$carFullOption = new GPSNavigation($carWithSunRoofAndLeatherSeats);
// 5. Kiểm tra xe với tùy chọn đầy đủ
echo $carFullOption-> description();
echo " giá " . $carFullOption-> cost();
Code language: PHP (php)
Kết quả như sau: Xe Suv, cửa sổ trời, ghế bọc da, định vị toàn cầu GPS giá 33300
Lời kết
Decorator Pattern là pattern khá hay trong việc mở rộng tính năng một class mà không thay đổi gì các class đang có. Áp dụng Decorator Pattern trong lập trình hướng đối tượng làm cho code trở nên uyển chuyển. Danh sách các Design pattern là rất nhiều, chúng ta sẽ còn gặp lại trong các bài viết về các mẫu lập trình khác.
Cảm ơn các bạn đã đọc.
Các bạn có thể tham khảo các bài viết hay về Laravel tại đây.
Hãy tham gia nhóm Học lập trình để thảo luận thêm về các vấn đề cùng quan tâm.
Nguồn tham khảo: allaravel
Leave a Reply