Itu biasanya dilakukan dengan menggunakan pesan. Anda dapat menemukan banyak detail dalam pertanyaan lain di situs ini, seperti di sini atau di sana .
Untuk menjawab contoh spesifik Anda, cara untuk pergi adalah dengan mendefinisikan Message
kelas kecil yang dapat diproses objek Anda, misalnya:
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);
}
}
Dengan cara ini Anda tidak "mencemari" Obj
antarmuka kelas Anda dengan metode terkait komponen. Beberapa komponen dapat memilih untuk memproses pesan, beberapa mungkin mengabaikannya.
Anda bisa mulai dengan memanggil metode ini langsung dari objek lain:
Message msg(obj1, "EmitForce(5.0,0.0,0.0)");
obj2.ProcessMessage(msg);
Dalam kasus ini, obj2
's Physics
akan memilih pesan, dan melakukan apa pengolahan yang perlu dilakukan. Ketika selesai, itu akan:
- Kirim pesan "SetPosition" ke diri sendiri, bahwa
Position
komponen akan memilih;
- Atau langsung mengakses
Position
komponen untuk modifikasi (sangat salah untuk desain berbasis komponen murni, karena Anda tidak dapat mengasumsikan setiap objek memiliki Position
komponen, tetapi Position
komponen itu bisa menjadi persyaratan Physics
).
Biasanya merupakan ide bagus untuk menunda pemrosesan pesan yang sebenarnya ke pembaruan komponen berikutnya . Memprosesnya dengan segera dapat berarti mengirim pesan ke komponen lain dari objek lain, jadi mengirim hanya satu pesan dapat dengan cepat berarti tumpukan spageti yang tidak dapat dipisahkan.
Anda mungkin harus menggunakan sistem yang lebih maju di kemudian hari: antrian pesan tidak sinkron, mengirim pesan ke sekelompok objek, mendaftar per komponen / tidak mendaftar dari pesan, dll
The Message
kelas dapat menjadi wadah generik untuk string sederhana seperti yang ditunjukkan di atas, tetapi pengolahan string di runtime tidak benar-benar efisien. Anda bisa mencari wadah nilai generik: string, integer, floats ... Dengan nama atau lebih baik lagi, ID, untuk membedakan berbagai jenis pesan. Atau Anda juga bisa mendapatkan kelas dasar agar sesuai dengan kebutuhan spesifik. Dalam kasus Anda, Anda dapat membayangkan sebuah EmitForceMessage
yang berasal dari Message
dan menambahkan vektor gaya yang diinginkan -tapi waspadalah terhadap biaya runtime RTTI jika Anda melakukannya.