Tiếp theo phần 2, chúng ta hãy cùng cafedev làm demo về decorator pattern nhằm giúp ace dễ hiểu khi áp dụng trên các ngôn ngữ khác nhau. Ace có thể tham khảo thêm các bài khác tại series Design Pattern tại đây.

Trong bài viết này, sẽ thảo luận về thiết kế và thực hiện Decorator Pattern cho vấn đề Pizza. Bạn nên thử nó trước tiên.

Sơ đồ lớp mới

  • Pizza  đóng vai trò là lớp thành phần trừu tượng của chúng ta.
  • Có bốn thành phần cụ thể là PeppyPaneer , FarmHouse , Margherita , ChickenFiesta .
  • ToppingsDecorator là người trang trí trừu tượng của chúng ta và FreshTomato , Paneer , Jalapeno , Barbeque là người trang trí.

Dưới đây là phần triển khai java của thiết kế trên.

// Java program to demonstrate Decorator 
// pattern 
  
// Abstract Pizza class (All classes extend 
// from this) 
abstract class Pizza 
{ 
    // it is an abstract pizza 
    String description = "Unkknown Pizza"; 
  
    public String getDescription() 
    { 
        return description; 
    } 
  
    public abstract int getCost(); 
} 
  
// The decorator class :  It extends Pizza to be 
// interchangable with it topings decorator can 
// also be implemented as an interface 
abstract class ToppingsDecorator extends Pizza 
{ 
    public abstract String getDescription(); 
} 
  
// Concrete pizza classes 
class PeppyPaneer extends Pizza 
{ 
    public PeppyPaneer() { description = "PeppyPaneer"; } 
    public int getCost() {  return 100; } 
} 
class FarmHouse extends Pizza 
{ 
    public FarmHouse() {  description = "FarmHouse"; } 
    public int getCost() { return 200; } 
} 
class Margherita extends Pizza 
{ 
    public Margherita()  { description = "Margherita"; } 
    public int getCost() { return 100;  } 
} 
class ChickenFiesta extends Pizza 
{ 
    public ChickenFiesta() { description = "ChickenFiesta";} 
    public int getCost() { return 200; } 
} 
class SimplePizza extends Pizza 
{ 
public SimplePizza() { description = "SimplePizza"; } 
public int getCost() {  return 50;  } 
} 
  
// Concrete toppings classes 
class FreshTomato extends ToppingsDecorator 
{ 
    // we need a reference to obj we are decorating 
    Pizza pizza; 
  
    public FreshTomato(Pizza pizza) { this.pizza = pizza; } 
    public String getDescription() { 
        return pizza.getDescription() + ", Fresh Tomato "; 
    } 
    public int getCost() { return 40 + pizza.getCost(); } 
} 
class Barbeque extends ToppingsDecorator 
{ 
    Pizza pizza; 
    public Barbeque(Pizza pizza) {  this.pizza = pizza;  } 
    public String getDescription() { 
        return pizza.getDescription() + ", Barbeque "; 
    } 
    public int getCost() { return 90 + pizza.getCost(); } 
} 
class Paneer extends ToppingsDecorator 
{ 
    Pizza pizza; 
    public Paneer(Pizza pizza)  {  this.pizza = pizza; } 
    public String getDescription() { 
        return pizza.getDescription() + ", Paneer "; 
    } 
    public int getCost()  {  return 70 + pizza.getCost(); } 
} 
  
// Other toppings can be coded in a similar way 
  
// Driver class and method 
class PizzaStore 
{ 
    public static void main(String args[]) 
    { 
        // create new margherita pizza 
        Pizza pizza = new Margherita(); 
        System.out.println( pizza.getDescription() + 
                         " Cost :" + pizza.getCost()); 
  
        // create new FarmHouse pizza 
        Pizza pizza2 = new FarmHouse(); 
  
        // decorate it with freshtomato topping 
        pizza2 = new FreshTomato(pizza2); 
  
        //decorate it with paneer topping 
        pizza2 = new Paneer(pizza2); 
  
        System.out.println( pizza2.getDescription() + 
                         " Cost :" + pizza2.getCost()); 
        Pizza pizza3 = new Barbeque(null);    //no specific pizza 
        System.out.println( pizza3.getDescription() + "  Cost :" + pizza3.getCost()); 
   } 
} 

Đầu ra:

Margherita Cost :100
FarmHouse, Fresh Tomato , Paneer Cost :310

Lưu ý cách chúng ta có thể thêm / xóa pizza và lớp phủ mới mà không thay đổi trong code đã thử nghiệm trước đó và lớp phủ và bánh pizza được tách rời.

// CPP program to demonstrate  
// Decorator pattern 
#include <iostream> 
#include <string> 
using namespace std; 
  
// Component  
class MilkShake 
{ 
public: 
    virtual string Serve() = 0; 
    virtual float price() = 0; 
}; 
  
  
// Concrete Component   
class BaseMilkShake : public MilkShake 
{ 
public: 
    string Serve() 
    { 
        return "MilkShake"; 
    } 
  
    float price() 
    { 
        return 30; 
    } 
}; 
  
// Decorator  
class MilkShakeDecorator: public MilkShake 
{ 
protected: 
    MilkShake *m_MilkShake; 
public: 
  
    MilkShakeDecorator(MilkShake *baseMilkShake): m_MilkShake(baseMilkShake){} 
  
    string Serve() 
    { 
        return m_MilkShake->Serve(); 
    } 
  
    float price() 
    { 
        return m_MilkShake->price(); 
    } 
}; 
  
  
// Concrete Decorator  
class MangoMilkShake: public MilkShakeDecorator 
{ 
public: 
    MangoMilkShake(MilkShake *baseMilkShake): MilkShakeDecorator(baseMilkShake){} 
  
    string Serve() 
    { 
        return m_MilkShake->Serve() + " decorated with Mango "; 
    } 
    float price() 
    { 
        return m_MilkShake->price() + 40; 
    } 
}; 
  
  
class VanillaMilkShake: public MilkShakeDecorator 
{ 
public: 
    VanillaMilkShake(MilkShake *baseMilkShake): MilkShakeDecorator(baseMilkShake){} 
  
    string Serve() 
    { 
        return m_MilkShake->Serve() + " decorated with Vanilla "; 
    } 
    float price() 
    { 
        return m_MilkShake->price() + 80; 
    } 
}; 
  
int main() 
{ 
  MilkShake *baseMilkShake = new BaseMilkShake(); 
  cout << "Basic Milk shake \n"; 
  cout << baseMilkShake -> Serve() << endl; 
  cout << baseMilkShake -> price() << endl;     
  
  MilkShake *decoratedMilkShake = new MangoMilkShake(baseMilkShake); 
  cout << "Mango decorated Milk shake \n"; 
  cout << decoratedMilkShake -> Serve() << endl; 
  cout << decoratedMilkShake -> price() << endl;     
      
  delete decoratedMilkShake; 
  
  decoratedMilkShake = new VanillaMilkShake(baseMilkShake); 
  cout << "Vanilla decorated Milk shake \n"; 
  cout << decoratedMilkShake -> Serve() << endl; 
  cout << decoratedMilkShake -> price() << endl;     
  
 delete decoratedMilkShake; 
 delete baseMilkShake; 
  return 0; 
}
Basic Milk shake
MilkShake
Price of MilkShake : 30
Mango decorated Milk shake
MilkShake decorated with Mango
Price of Mango MilkShake : 70
Vanilla decorated Milk shake
MilkShake decorated with Vanilla
Price of Vanilla MilkShake : 110

Cài ứng dụng cafedev để dễ dàng cập nhật tin và học lập trình mọi lúc mọi nơi tại đây.

Tài liệu từ cafedev:

Nếu bạn thấy hay và hữu ích, bạn có thể tham gia các kênh sau của cafedev để nhận được nhiều hơn nữa:

Chào thân ái và quyết thắng!

Đăng ký kênh youtube để ủng hộ Cafedev nha các bạn, Thanks you!