close up photo of programming of codes

codecungnhau.com

Một trang web về kỹ thuật lập trình

C++ Design Pattern: Composite

Composite là một mẫu thiết kế cấu trúc cho phép sắp xếp các đối tượng thành một cấu trúc giống như cây và làm việc với nó như thể nó là một đối tượng đơn lẻ.

Composite đã trở thành một giải pháp khá phổ biến cho hầu hết các vấn đề yêu cầu xây dựng cấu trúc cây. Tính năng tuyệt vời của Composite là khả năng chạy các phương thức đệ quy trên toàn bộ cấu trúc cây và tổng hợp kết quả.

Cách sử dụng mẫu

Cách sử dụng: Mẫu Composite khá phổ biến trong C++. Nó thường được sử dụng để biểu thị thứ bậc của các thành phần giao diện người dùng hoặc chương trình hoạt động với đồ thị.

Nhận dạng: Nếu bạn có cây đối tượng và mỗi đối tượng của cây là một phần của cùng một hệ thống phân cấp lớp, thì đây rất có thể là một composite. Nếu các phương thức của các lớp này ủy thác công việc cho các đối tượng con của cây và thực hiện nó thông qua lớp cơ sở / giao diện của hệ thống phân cấp, thì đây chắc chắn là một composite.

Chương trình mẫu

main.cpp

#include <algorithm>
#include <iostream>
#include <list>
#include <string>
/**
 * Lớp cơ sở Component khai báo các hoạt động chung cho cả các đối tượng 
 * đơn giản và phức tạp của một composition.
 */
class Component {
  /**
   * @var Component
   */
 protected:
  Component *parent_;
  /**
   * Tùy chọn, Component cơ sở có thể khai báo một giao diện để thiết lập và
   * truy cập thành phần cha trong cấu trúc cây. Nó cũng có thể cung cấp 
   * một số triển khai mặc định cho các phương thức này.
   */
 public:
  virtual ~Component() {}
  void SetParent(Component *parent) {
    this->parent_ = parent;
  }
  Component *GetParent() const {
    return this->parent_;
  }
  /**
   * Trong một số trường hợp, sẽ có lợi nếu xác định các hoạt động quản lý lớp 
   * con ngay trong lớp Component. Bằng cách này, bạn sẽ không cần hiển thị 
   * bất kỳ lớp component cụ thể nào với client, ngay cả trong quá trình tạo cây 
   * đối tượng. Nhược điểm là các phương thức này sẽ rỗng đối với các nút leaf.
   */
  virtual void Add(Component *component) {}
  virtual void Remove(Component *component) {}
  /**
   * Có thể cung cấp một phương thức cho phép client xác định liệu một 
   * component có nút con hay không.
   */
  virtual bool IsComposite() const {
    return false;
  }
  /**
   * Component có thể thực hiện một số hành vi mặc định hoặc để nó 
   * cho các lớp cụ thể (bằng cách khai báo phương thức trừu tượng).
   */
  virtual std::string Operation() const = 0;
};
/**
 * Lớp Lá (Leaf) đại diện cho các đối tượng cuối cùng của một cây.
 * Một nút lá không thể có con.
 *
 * Thông thường, các đối tượng Leaf thực hiện công việc thực tế, trong khi các 
 * đối tượng Composite chỉ ủy quyền cho các thành phần con của chúng.
 */
class Leaf : public Component {
 public:
  std::string Operation() const override {
    return "Leaf";
  }
};
/**
 * Lớp Composite đại diện cho các thành phần phức tạp có thể có con. Thông  
 * thường, các đối tượng Composite ủy thác công việc thực tế cho con cái của 
 * chúng và sau đó "tổng hợp" kết quả.
 */
class Composite : public Component {
  /**
   * @var \SplObjectStorage
   */
 protected:
  std::list<Component *> children_;
 public:
  /**
   * Một đối tượng Composite có thể thêm hoặc bớt các thành phần khác (cả 
   * đơn giản hoặc phức tạp) vào hoặc khỏi danh sách con của nó.
   */
  void Add(Component *component) override {
    this->children_.push_back(component);
    component->SetParent(this);
  }
  /**
   * Hãy nhớ rằng phương thức này xóa con trỏ đến danh sách nhưng không 
   * giải phóng bộ nhớ, bạn nên thực hiện theo cách thủ công hoặc tốt hơn 
   * là sử dụng con trỏ thông minh smart_pointer.
   */
  void Remove(Component *component) override {
    children_.remove(component);
    component->SetParent(nullptr);
  }
  bool IsComposite() const override {
    return true;
  }
  /**
   * Composite thực thi logic chính của nó theo một cách cụ thể. Nó duyệt đệ 
   * quy qua tất cả các con của nó, thu thập và tổng hợp kết quả của chúng. 
   * Vì các con của composite truyền những lệnh gọi này cho con của chúng 
   * và cứ thế, kết quả là toàn bộ cây đối tượng được duyệt qua.
   */
  std::string Operation() const override {
    std::string result;
    for (const Component *c : children_) {
      if (c == children_.back()) {
        result += c->Operation();
      } else {
        result += c->Operation() + "+";
      }
    }
    return "Branch(" + result + ")";
  }
};
/**
 * Client hoạt động với tất cả các component thông qua giao diện cơ sở.
 */
void ClientCode(Component *component) {
  // ...
  std::cout << "RESULT: " << component->Operation();
  // ...
}
/**
 * Nhờ các hoạt động quản lý lớp con được khai báo trong lớp Component cơ sở, 
 * client có thể hoạt động với bất kỳ thành phần nào, đơn giản hay phức tạp mà 
 * không phụ thuộc vào các lớp cụ thể của chúng.
 */
void ClientCode2(Component *component1, Component *component2) {
  // ...
  if (component1->IsComposite()) {
    component1->Add(component2);
  }
  std::cout << "RESULT: " << component1->Operation();
  // ...
}
/**
 * Bằng cách này, client có thể hỗ trợ các thành phần lá đơn giản...
 */
int main() {
  Component *simple = new Leaf;
  std::cout << "Client: I've got a simple component:\n";
  ClientCode(simple);
  std::cout << "\n\n";
  /**
   * ...cũng như các thành phần phức tạp.
   */
  Component *tree = new Composite;
  Component *branch1 = new Composite;
  Component *leaf_1 = new Leaf;
  Component *leaf_2 = new Leaf;
  Component *leaf_3 = new Leaf;
  branch1->Add(leaf_1);
  branch1->Add(leaf_2);
  Component *branch2 = new Composite;
  branch2->Add(leaf_3);
  tree->Add(branch1);
  tree->Add(branch2);
  std::cout << "Client: Now I've got a composite tree:\n";
  ClientCode(tree);
  std::cout << "\n\n";
  std::cout << "Client: I don't need to check the components classes even when managing the tree:\n";
  ClientCode2(tree, simple);
  std::cout << "\n";
  delete simple;
  delete tree;
  delete branch1;
  delete branch2;
  delete leaf_1;
  delete leaf_2;
  delete leaf_3;
  return 0;
}

Kết quả

Client: I've got a simple component:
RESULT: Leaf
Client: Now I've got a composite tree:
RESULT: Branch(Branch(Leaf+Leaf)+Branch(Leaf))
Client: I don't need to check the components classes even when managing the tree:
RESULT: Branch(Branch(Leaf+Leaf)+Branch(Leaf)+Leaf)

Đã đăng vào

trong

,

bởi

Bình luận

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *