Nội dung
Decorator là một mẫu cấu trúc cho phép thêm động các hành vi mới vào các đối tượng bằng cách đặt chúng bên trong các đối tượng bọc đặc biệt.
Sử dụng decorator, có thể bọc các đối tượng vô số lần vì cả đối tượng đích và decorator đều tuân theo cùng một giao diện. Kết quả đối tượng sẽ nhận được một hành vi xếp chồng của tất cả các wrapper.
Cách sử dụng mẫu
Sử dụng: Decorator khá chuẩn trong mã C++, đặc biệt là trong mã liên quan đến luồng.
Nhận dạng: Decorator có thể được nhận dạng bởi các hàm tạo hoặc phương thức khởi tạo chấp nhận các đối tượng của cùng một lớp hoặc giao diện như lớp hiện tại.
Chương trình mẫu
main.cpp
/**
* Giao diện Component cơ sở xác định các hoạt động có thể được thay đổi bởi
* decorator.
*/
class Component {
public:
virtual ~Component() {}
virtual std::string Operation() const = 0;
};
/**
* Concrete Component cung cấp các triển khai mặc định của các hoạt động.
* Có thể có một số biến thể của các lớp này.
*/
class ConcreteComponent : public Component {
public:
std::string Operation() const override {
return "ConcreteComponent";
}
};
/**
* Lớp Decorator cơ sở tuân theo giao diện tương tự như các thành phần khác.
* Mục đích chính của lớp này là xác định giao diện bao bọc cho tất cả các Concrete
* Component. Việc triển khai mặc định của mã wrap có thể bao gồm một trường
* để lưu trữ một component được bọc và phương tiện để khởi tạo nó.
*/
class Decorator : public Component {
/**
* @var Component
*/
protected:
Component* component_;
public:
Decorator(Component* component) : component_(component) {
}
/**
* Decorator ủy quyền cho tất cả các component được bao bọc.
*/
std::string Operation() const override {
return this->component_->Operation();
}
};
/**
* Concrete Decorator gọi đối tượng được bọc và thay đổi kết quả của nó
* theo một cách nào đó.
*/
class ConcreteDecoratorA : public Decorator {
/**
* Decorator có thể gọi việc thực thi của hoạt động cha, thay vì gọi trực
* tiếp đối tượng được bao bọc. Cách tiếp cận này đơn giản hóa việc
* mở rộng các lớp decorator.
*/
public:
ConcreteDecoratorA(Component* component) : Decorator(component) {
}
std::string Operation() const override {
return "ConcreteDecoratorA(" + Decorator::Operation() + ")";
}
};
/**
* Decorator có thể thực hiện hành vi của chúng trước hoặc sau lời gọi
* đến một đối tượng được bao bọc.
*/
class ConcreteDecoratorB : public Decorator {
public:
ConcreteDecoratorB(Component* component) : Decorator(component) {
}
std::string Operation() const override {
return "ConcreteDecoratorB(" + Decorator::Operation() + ")";
}
};
/**
* Client hoạt động với tất cả các đối tượng bằng giao diện Component.
* Bằng cách này, nó có thể độc lập với các lớp cụ thể của các thành phần
* mà nó hoạt động cùng.
*/
void ClientCode(Component* component) {
// ...
std::cout << "RESULT: " << component->Operation();
// ...
}
int main() {
/**
* Bằng cách này, client có thể hỗ trợ cả hai component đơn giản...
*/
Component* simple = new ConcreteComponent;
std::cout << "Client: I've got a simple component:\n";
ClientCode(simple);
std::cout << "\n\n";
/**
* ...cũng như decorator.
*
* Lưu ý cách decorator có thể bọc không chỉ các component
* đơn giản mà còn cả các decorator khác.
*/
Component* decorator1 = new ConcreteDecoratorA(simple);
Component* decorator2 = new ConcreteDecoratorB(decorator1);
std::cout << "Client: Now I've got a decorated component:\n";
ClientCode(decorator2);
std::cout << "\n";
delete simple;
delete decorator1;
delete decorator2;
return 0;
}
Kết quả
Client: I've got a simple component:
RESULT: ConcreteComponent
Client: Now I've got a decorated component:
RESULT: ConcreteDecoratorB(ConcreteDecoratorA(ConcreteComponent))
Để lại một bình luận