Điều đó thường được thực hiện bằng cách sử dụng tin nhắn. Bạn có thể tìm thấy rất nhiều chi tiết trong các câu hỏi khác trên trang web này, như ở đây hoặc ở đó .
Để trả lời ví dụ cụ thể của bạn, một cách để đi là xác định một Message
lớp nhỏ mà các đối tượng của bạn có thể xử lý, ví dụ:
struct Message
{
Message(const Objt& sender, const std::string& msg)
: m_sender(&sender)
, m_msg(msg) {}
const Obj* m_sender;
std::string m_msg;
};
void Obj::Process(const Message& msg)
{
for (int i=0; i<m_components.size(); ++i)
{
// let components do some stuff with msg
m_components[i].Process(msg);
}
}
Bằng cách này, bạn không "làm ô nhiễm" bạn Obj
giao diện lớp với các phương thức liên quan đến thành phần. Một số thành phần có thể chọn xử lý tin nhắn, một số có thể bỏ qua nó.
Bạn có thể bắt đầu bằng cách gọi phương thức này trực tiếp từ một đối tượng khác:
Message msg(obj1, "EmitForce(5.0,0.0,0.0)");
obj2.ProcessMessage(msg);
Trong trường hợp này, obj2
chúng Physics
tôi sẽ chọn tin nhắn và thực hiện bất kỳ xử lý nào cần thực hiện. Khi hoàn thành, nó sẽ:
- Gửi tin nhắn "SetPocation" cho chính mình, rằng
Position
thành phần sẽ chọn;
- Hoặc truy cập trực tiếp vào
Position
thành phần để sửa đổi (khá sai đối với thiết kế dựa trên thành phần thuần túy, vì bạn không thể giả sử mọi đối tượng đều có một Position
thành phần, nhưng Position
thành phần đó có thể là một yêu cầu Physics
).
Nói chung, nên trì hoãn việc xử lý thông báo thực tế đến bản cập nhật của thành phần tiếp theo . Xử lý nó ngay lập tức có thể có nghĩa là gửi tin nhắn đến các thành phần khác của các đối tượng khác, vì vậy gửi chỉ một tin nhắn có thể nhanh chóng có nghĩa là một chồng spaghetti không thể khắc phục.
Bạn có thể sẽ phải sử dụng một hệ thống nâng cao hơn sau này: hàng đợi tin nhắn không đồng bộ, gửi tin nhắn đến nhóm đối tượng, đăng ký theo từng thành phần / không đăng ký từ tin nhắn, v.v.
Các Message
lớp có thể là một thùng chứa chung cho một chuỗi đơn giản như trên, nhưng chế biến dây trong thời gian chạy là không thực sự hiệu quả. Bạn có thể tìm một thùng chứa các giá trị chung: chuỗi, số nguyên, số float ... Với một tên hoặc tốt hơn là ID, để phân biệt các loại thông báo khác nhau. Hoặc bạn cũng có thể lấy được một lớp cơ sở để phù hợp với nhu cầu cụ thể. Trong trường hợp của bạn, bạn có thể tưởng tượng một EmitForceMessage
xuất phát từ Message
và thêm vectơ lực mong muốn - nhưng hãy cẩn thận với chi phí thời gian chạy của RTTI nếu bạn làm như vậy.