Saya telah membuat dua kelas abstrak Subject dan Observer yang mendefinisikan antarmuka pola Observer klasik. Saya berasal dari mereka untuk menerapkan pola Observer. Seorang pengamat mungkin terlihat seperti ini:
void MyClass::Update(Subject *subject)
{
if(subject == myService_)
{
DoSomething();
}
else if(subject == myOtherService_)
{
DoSomethingElse();
}
}
Ini baik dan itu memberitahu saya siapa yang mengubah sesuatu. Namun, itu tidak memberi tahu saya apa yang berubah. Terkadang ini ok karena saya hanya akan meminta Subjek untuk data terbaru, tetapi di lain waktu saya perlu tahu apa yang sebenarnya berubah pada Subjek. Saya perhatikan di Jawa mereka memiliki metode notifyObservers () dan metode notifyObservers (Object arg) untuk menentukan rincian tentang apa yang berubah.
Dalam kasus saya, saya perlu tahu apakah salah satu dari beberapa tindakan berbeda terjadi pada subjek dan, jika itu tindakan tertentu, untuk mengetahui bilangan bulat yang terkait dengan tindakan itu.
Jadi pertanyaan saya adalah:
- apa cara C ++ untuk melewatkan argumen umum (seperti yang dilakukan Java)?
- Apakah Pengamat bahkan merupakan pola terbaik? Mungkin semacam sistem acara?
MEMPERBARUI
Saya menemukan artikel ini yang berbicara tentang templating pola Observer: Menerapkan pola Subjek / Observer dengan templat . Ini membuat saya bertanya-tanya apakah Anda bisa membuat templat argumen.
Saya menemukan pertanyaan overflow tumpukan ini yang berbicara tentang templating argumen: Pola Pengamat Subjek berbasis template - Haruskah saya menggunakan static_cast atau dynamic_cast . Namun, OP tampaknya memiliki masalah yang belum ada yang menjawab.
Hal lain yang bisa saya lakukan adalah mengubah metode Pembaruan untuk mengambil objek EventArg seperti pada:
void MyClass::Update(Subject *subject, EventArg arg)
{
...
Dan kemudian membuat subclass dari EventArg untuk data argumen tertentu, dan kemudian saya kira melemparkannya kembali ke subclass spesifik dalam metode pembaruan.
PEMBARUAN 2
Juga menemukan artikel, Saat membuat kerangka kerja c ++ berbasis pesan yang tidak sinkron; bagian 2 yang membahas perihal Subjek mengkomunikasikan perincian tentang apa yang berubah.
Saya sekarang serius mempertimbangkan untuk menggunakan Boost.Signals . Menggunakan pola pengamat saya sendiri masuk akal ketika itu sederhana, tetapi templating jenis dan argumen mulai menjadi rumit. Dan saya mungkin membutuhkan keamanan thread dari Boost.Signals2.
PEMBARUAN 3
Saya juga menemukan beberapa artikel menarik tentang pola pengamat:
Generalisasi Pengamat oleh Herb Sutter
Menerapkan Pola Pengamat di C ++ - Bagian 1
Pengalaman Menerapkan Pola Desain Pengamat (Bagian 2)
Pengalaman Menerapkan Pola Desain Pengamat (Bagian 3)
Namun, saya telah beralih implementasi saya untuk menggunakan Boost.Signals yang, walaupun mungkin sedikit membengkak untuk tujuan saya, berhasil bekerja. Dan mungkin kekhawatiran tentang kembung atau kecepatan tidak relevan.
sumber
Jawaban:
Apakah C ++ atau JAVA, Pemberitahuan kepada pengamat dapat datang bersama dengan informasi tentang apa yang diubah. Metode notifyObservers (Object arg) yang sama juga dapat digunakan dalam C ++.
Secara umum, masalah akan tetap adalah bahwa mungkin ada banyak subjek yang dikirim ke satu atau beberapa pengamat dan karenanya,
class arg
tidak dapat dikodekan dengan keras.Biasanya, cara terbaik yang harus dilakukan adalah membuat arg dalam bentuk pesan umum / token yang membentuk tipe data yang sama untuk berbagai kelas tetapi nilainya berbeda untuk kelas yang diamati berbeda. Atau, jika semua nilai notifikasi tersebut diturunkan dari kelas pada beberapa kelas berbasis yang umum untuk semua.
Untuk pola pengamat, itu adalah penting bahwa Arg tipe data tidak sulit kode antara observee dan pengamat - yang lain itu adalah kopling yang membuat hal-hal sulit untuk berkembang.
EDIT
Jika Anda ingin pengamat itu tidak hanya mengamati tetapi juga perlu melakukan banyak tugas lain berdasarkan apa yang telah berubah , Anda juga dapat memeriksa pola Pengunjung . Dalam pola pengunjung, pengamat / pengunjung memanggil objek yang dimodifikasi dan karenanya tidak hanya bisa tahu apa modifikasi itu tetapi sebenarnya dapat bekerja di dalamnya
sumber
Object
(void *
,boost::any
atau sesuatu yang serupa generik) daripada jika Anda melewati tipe tertentu, karena dengan tipe spesifik Anda akan melihat pada waktu kompilasi bahwa sesuatu berubah, sedangkan dengan tipe generik itu akan mengkompilasi dan berhenti bekerja, karena pengamat tidak akan dapat bekerja dengan data aktual yang diteruskan.std::function
Boostboost::function
, Gtk +GClosure
, metode terikat python dll.), Jadi saya hanya mendefinisikan metode dengan tanda tangan yang sesuai dan meminta sistem untuk membuat aktual pengamat. Kopling ini memang hanya satu arah, subjek mendefinisikan antarmuka untuk pengamat, tetapi tidak memiliki gagasan tentang implementasinya.Ada beberapa cara untuk mengirim argumen peristiwa umum "Suka Java" di C ++.
1) Nyatakan argumen event sebagai void * dan serahkan ke kelas yang tepat di event handler.
2) Nyatakan argumen event sebagai penunjuk / ref ke kelas / antarmuka baru seperti (sebagai tanggapan atas contoh Anda)
Dan mintalah kelas argumen acara yang sebenarnya berasal dari kelas ini.
Adapun pertanyaan Anda tentang pengamat berbasis template periksa
http://www.codeproject.com/Articles/3267/Implementing-a-Subject-Observer-pattern-with-templ
sumber
Saya tidak tahu apakah ini nama kanonik, tetapi dari masa kecil saya Smalltalk saya ingat istilah "aspek" untuk mengidentifikasi apa yang telah berubah pada yang diamati.
Ini tidak serumit ide Anda tentang EventArg (dan mensubklasifikasikannya); itu hanya melewati string (bahkan bisa berupa konstanta integer) dari yang dapat diamati kepada pengamat.
Plus: Hanya ada dua metode sederhana (
update(observable)
danupdateAspect(observable, aspect)
Minus: Pengamat mungkin harus meminta informasi lebih lanjut yang dapat diamati (yaitu, "bilangan bulat" Anda)
sumber