Câu hỏi hay! Trước khi tôi nhận được các câu hỏi cụ thể mà bạn đã hỏi, tôi sẽ nói: đừng đánh giá thấp sức mạnh của sự đơn giản. Tenpn là đúng. Hãy nhớ rằng tất cả những gì bạn đang cố gắng thực hiện với các phương pháp này là tìm một cách thanh lịch để trì hoãn một cuộc gọi chức năng hoặc tách rời người gọi khỏi callee. Tôi có thể đề xuất coroutines như một cách trực quan đáng ngạc nhiên để giảm bớt một số vấn đề đó, nhưng đó là một chủ đề nhỏ. Đôi khi, tốt hơn hết là bạn chỉ cần gọi hàm và sống với thực tế là thực thể A được ghép trực tiếp với thực thể B. Xem YAGNI.
Điều đó nói rằng, tôi đã sử dụng và hài lòng với mô hình tín hiệu / khe cắm kết hợp với việc truyền tin nhắn đơn giản. Tôi đã sử dụng nó trong C ++ và Lua cho một tiêu đề iPhone khá thành công có lịch trình rất chặt chẽ.
Đối với trường hợp tín hiệu / khe cắm, nếu tôi muốn thực thể A làm điều gì đó để đáp lại thực thể B đã làm (ví dụ: mở khóa cửa khi có thứ gì đó chết) tôi có thể có thực thể A đăng ký trực tiếp vào sự kiện tử vong của thực thể B. Hoặc có thể thực thể A sẽ đăng ký vào từng nhóm thực thể, tăng số lượt truy cập cho mỗi sự kiện được bắn và mở khóa cửa sau khi N trong số họ đã chết. Ngoài ra, "nhóm thực thể" và "N của chúng" thường sẽ được thiết kế xác định trong dữ liệu cấp. (Bên cạnh đó, đây là một lĩnh vực mà các coroutines thực sự có thể tỏa sáng, ví dụ WaitForMultipl ("Dying", entA, entB, entC); door.Unlock ();)
Nhưng điều đó có thể trở nên cồng kềnh khi có các phản ứng được kết hợp chặt chẽ với mã C ++ hoặc các sự kiện trò chơi phù du vốn có: gây sát thương, nạp lại vũ khí, gỡ lỗi, phản hồi AI dựa trên vị trí do người chơi điều khiển. Đây là nơi thông điệp đi qua có thể điền vào các khoảng trống. Về cơ bản, nó tập trung vào một cái gì đó như, "nói cho tất cả các thực thể trong khu vực này nhận sát thương trong 3 giây" hoặc "bất cứ khi nào bạn hoàn thành vật lý để tìm ra người tôi đã bắn, hãy bảo họ chạy chức năng kịch bản này." Thật khó để tìm ra cách thực hiện điều đó một cách độc đáo bằng cách xuất bản / đăng ký hoặc tín hiệu / vị trí.
Điều này có thể dễ dàng bị quá mức (so với ví dụ của tenpn). Nó cũng có thể là không hiệu quả nếu bạn có nhiều hành động. Nhưng mặc dù nhược điểm của nó, cách tiếp cận "thông điệp và sự kiện" này rất phù hợp với mã trò chơi theo kịch bản (ví dụ như trong Lua). Mã script có thể định nghĩa và phản ứng với các thông điệp và sự kiện của chính nó mà không cần chăm sóc mã C ++. Và mã tập lệnh có thể dễ dàng gửi tin nhắn kích hoạt mã C ++, như thay đổi cấp độ, phát âm thanh hoặc thậm chí chỉ để vũ khí đặt mức độ thiệt hại mà thông điệp TakeDamage mang lại. Nó giúp tôi tiết kiệm rất nhiều thời gian vì tôi không phải liên tục đùa giỡn với luabind. Và nó cho phép tôi giữ tất cả mã nguồn của mình ở một nơi, vì không có nhiều mã. Khi được ghép đúng cách,
Ngoài ra, kinh nghiệm của tôi với trường hợp sử dụng # 2 là bạn nên xử lý nó như một sự kiện theo hướng khác. Thay vì hỏi sức khỏe của thực thể là gì, hãy tổ chức một sự kiện / gửi tin nhắn bất cứ khi nào sức khỏe tạo ra sự thay đổi đáng kể.
Về giao diện, btw, tôi đã kết thúc với ba lớp để thực hiện tất cả điều này: Eventhost, EventClient và MessageClient. Eventhosts tạo các vị trí, EventCl Client đăng ký / kết nối với chúng và MessageCl Client liên kết một đại biểu với một tin nhắn. Lưu ý rằng mục tiêu ủy nhiệm của MessageClient không nhất thiết phải là cùng một đối tượng sở hữu liên kết. Nói cách khác, MessageCl Client có thể tồn tại chỉ để chuyển tiếp tin nhắn đến các đối tượng khác. FWIW, ẩn dụ máy chủ / máy khách là loại không phù hợp. Nguồn / Chìm có thể là khái niệm tốt hơn.
Xin lỗi, tôi hơi huyên thuyên ở đó. Đó là câu trả lời đầu tiên của tôi :) Tôi hy vọng nó có ý nghĩa.