+4

Design Pattern - Decorator

1. Decorator là gì?

  • Decorator là một trong 23 mẫu thiết kế Gang of Four mô tả làm thế nào để giải quyết vấn đề thiết kế các phần mềm mang tính hướng đối tượng một các linh hoạt và có tính tái sử dụng.
  • Decorator cho phép người dùng thêm các tính năng mới vào một đối tượng đã có mà không làm thay đổi cấu trúc lớp của nó.
  • Decorator này nằm trong nhóm mẫu thiết kế mang tính cấu trúc (Structural pattern) bởi vì nó thể hiện như là đóng gói của một lớp đã tồn tại.

2. Khi nào sử dụng Decorator?

  • Khi bạn muốn thêm các tính năng cho một đối tượng đã có một cách linh động trong thời gian chạy (run-time) mà không làm thay đổi đến các đối tượng khác của cùng lớp.
  • Khi việc thêm tính năng mới khiến bạn phải tạo ra nhiều lớp kế thừa và mã nguồn của bạn trở nên đồ sộ

3. Ý tưởng

  • Component: giao diện (interface) chung để các đối tượng cần thêm chức năng trong quá trình chạy thì triển khai giao diện này.
  • ConcreteComponent : Một cài đặt cho giao diện Component mà nó định nghĩa một đối tượng cần thêm các chức năng trong quá trình chạy.
  • Decorator : một lớp trừu tượng dùng để duy trì một tham chiếu của đối tượng thành phần và đồng thời cài đặt các thành phần của giao diện.
  • ConcreteDecorator : Một cài đặt của Decorator, bổ sung thêm các chức năng vào đối tượng thành phần.

4. Triển khai

4.1. Bài toán

Bài toán mình đặt ra để thử triển khai Decorator Design Pattern là bán bún đậu với các món ăn kèm có thể thêm vào, như:

  • Bún đậu có thêm chả cốm: + 7k
  • Bún đậu có thêm nem rán: + 5k

4.2. Cài đặt

Chúng ta sẽ có interface là MonAn

\\ MonAn.java

public interface MonAn {
  int layDonGia();
}

Và class BunDau sẽ thực thi interface MonAn trên

\\ BunDau.java

class BunDau implements MonAn {
  @Override
  public int layDonGia() {
    \\ Mặc định mình bán bún đậu không kèm món ăn thêm thì có giá 10k
    return 10;
  }
}

Giờ chúng ta định nghĩa một lớp trừu tượng Decorator

\\ MonAnDecorator.java

abstract class MonAnDecorator implements MonAn {
  \\ một tham chiếu của đối tượng thành phần mà được bổ sung thêm chức năng
  private MonAn monAn;
  
  public MonAnDecorator(MonAn monAn) {
    this.monAn = monAn;
  }
  
  @Override
  public int layDonGia() {
    return monAn.layDonGia();
  }
}

Và các lớp Decorator cụ thể thêm các chức năng bổ sung

\\ MonAnThemChaCom.java

class MonAnThemChaCom extends MonAnDecorator {
  public MonAnThemChaCom(MonAn monAn) {
    super(monAn);
  }
  
  @Override
  public int layDonGia() {
    \\ Món ăn nào có thêm chả cốm mình sẽ tính thêm 7k
    return super.layDonGia() + 7;
  }
}
\\ MonAnThemNemRan.java

class MonAnThemNemRan extends MonAnDecorator {
  public MonAnThemNemRan(MonAn monAn) {
    super(monAn);
  }
  
  @Override
  public int layDonGia() {
    \\ Món ăn nào có thêm nem rán thì mình sẽ tính thêm 5k
    return super.layDonGia() + 5;
  }
}

Và cần một chương trình để chạy các cài đặt trên

\\ Main.java

public class Main {
  public static void main(String[] args) {
    MonAn bunDau = new BunDau();
    System.out.println("Giá bún đậu: " + bunDau.layDonGia());
    
    MonAn bunDauChaCom = new MonAnThemChaCom(bunDau);
    System.out.println("Giá bún đậu có thêm chả cốm: " + bunDauChaCom.layDonGia());
    
    MonAn bunDauNemRan = new MonAnThemNemRan(bunDau);
    System.out.println("Giá bún đậu có thêm nem rán: " + bunDauNemRan.layDonGia());
    
    MonAn bunDauChaComNemRan = new MonAnThemNemRan(bunDauChaCom);
    System.out.println("Giá bún đậu có thêm chả cốm và nem rán: " + bunDauChaComNemRan.layDonGia());
  }
}

Sau khi chạy chương trình trên thì chúng ta nhận được kết quả như sau:

5. Kết luận

Trên đây là những kiến thức mình đã tìm hiểu được về Decorator Design Pattern, hy vọng sẽ giúp ích được phần nào đó cho những ai đang muốn tìm hiểu về Design pattern này. Nếu thấy bài viết của mình chưa được đúng, hãy giúp mình bằng cách thêm nhận xét vào phần comment bên dưới nhé. Cảm ơn bạn đã quan tâm đến bài viết.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí