escena
- Observador / Acontecimiento, son modelo de "Colaboración de componentes" para resolver el problema del marco de colaboración y aplicación
- La motivación: En el proceso de construcción de software, la necesidad de construir ciertos objetos de un "aviso - dependencias", es decir, el estado de un objeto (objeto de destino) se cambia, todos los objetos dependientes (objetos observador) serán notificados Si dicha dependencia demasiado de cerca, el software no será así para resistir el cambio
- la tecnología orientada a objetos, esta dependencia puede debilitarse, Dependencia formar una estable, reduciendo el software del sistema de acoplamiento
Ejemplos
MainForm1.cpp
1 clase MainForm: pública Formulario 2 { 3 Cuadro de texto * txtFilePath; 4 TextBox * txtFileNumber; 5 ProgressBar * progressBar; 6 7 pública : 8 vacío Button1_Click () { 9 10 cuerdas rutaArchivo = txtFilePath-> getText (); 11 int número = atoi (txtFileNumber-> getText () c_str ().); 12 13 FileSplitter divisor (filePath, número, progressBar); 14 15 splitter.split (); 16 17 } 18 };
FileSplitter1.cpp
1 clase FileSplitter 2 { 3 cadena m_filePath; 4 int m_fileNumber; 5 ProgressBar * m_progressBar; 6 7 público : 8 FileSplitter ( const cadena y filePath, int FileNumber, ProgressBar * progressBar): 9 m_filePath (filePath), 10 m_fileNumber (FileNumber), 11 m_progressBar (progressBar) { 12 } 13 14 void split () { 15 16 @ 1 leer los documentos 17. 18 es // 2. Los lotes pequeños para escribir en el fichero de 19. Para ( int I = 0 ; I <m_fileNumber; I ++ ) { 20 es // ... 21 es un flotador progressValue = m_fileNumber; 22 es progressValue = (I + 1. ) / progressValue; 23 es m_progressBar-> el setValue (progressValue); 24 } 25 26 es } 27 };
- programa divisor de archivo para archivos de gran tamaño, es necesario dividir la barra de progreso muestra el progreso
- MainForm1 dos recogida de parámetros de entrada de usuario, se transmite a FIleSplitter1
- Pregunta: violación de la Dependencia Inversión Principio. Realización (FileSplitter) se basan detalles (ProgressBar), y los detalles son susceptibles de cambio (por ejemplo, un interruptor tarde para Etiqueta muestran avances, o ninguna interfaz gráfica en la plataforma Linux, con ... representan el progreso)
- Dependencia: se refiere al nivel de compilador-dependiente (A B dependiente, A tiempo de compilación necesarios para compilar B)
- No confíe en los detalles, pero dependerá de lo abstracto
- control ProgressBar es una notificación específica, está disponible de forma abstracta representación (Interfaz IProgress)
MainForm2.cpp
1 clase MainForm: público de forma, pública IProgress 2 { 3 Cuadro de texto * txtFilePath; 4 TextBox * txtFileNumber; 5 6 ProgressBar * progressBar; 7 8 pública : 9 nula Button1_Click () { 10 11 cuerdas rutaArchivo = txtFilePath-> getText (); 12 int número = atoi (txtFileNumber-> getText () c_str ().); 13 14 ConsoleNotifier CN; 15 16 FileSplitter divisor (filePath, número); 17 18 splitter.addIProgress ( este ); // 订阅通知 19 splitter.addIProgress (y cn); // 订阅通知 20 21 splitter.split (); 22 23 splitter.removeIProgress ( este ); 24 25 } 26 27 virtual void DoProgress ( float valor) { 28 progressBar-> setValue (valor); 29 } 30 }; 31 32 claseConsoleNotifier: público IProgress { 33 pública : 34 virtual void DoProgress ( float valor) { 35 cout << " " ; 36 } 37 };
FileSplitter2.cpp
. 1 clase IProgress { 2 pública : . 3 virtual void DoProgress ( un flotador valor) = 0 ; . 4 Virtual ~ IProgress () {} . 5 }; . 6 . 7 clase FileSplitter . 8 { . 9 Cadena m_filePath; 10 int m_fileNumber; . 11 12 es List <IProgress *> m_iprogressList; // mecanismo de notificación abstracto para soportar una pluralidad de observadores 13 es 14 pública : 15 FileSplitter ( const cadenaFilePath y, int FileNumber): 16 m_filePath (filePath), . 17 m_fileNumber (FileNumber) { 18 es 19. } 20 es 21 es void split () { 22 es 23 es // 1. archivo grande leer 24 25 @ 2 a pequeños lotes archivo de escritura 26 es de ( int I = 0 ; I <m_fileNumber; I ++ ) { 27 // ... 28 29 un flotador progressValue = m_fileNumber; 30 progressValue = (I + . 1 ) /pro gre ssValue; 31 onProgress (pro gre ssValue); // 发送通知 32 } 33 34 } 35 36 37 vacío addIProgress (* Progreso Progreso) { 38 m_iprogressList.push_back (PROGRESS); 39 } 40 41 void removeIProgress (* Progreso Progreso) { 42 m_i pro gre Asli st.remove (PROGRESS); 43 } 44 45 protegida : 46 virtual void onProgress ( float valor) { 47 48 Lista <IProgress *> :: = iterador itor m_iprogressList.begin (); 49 50 , mientras que (itor =! M_iprogressList.end ()) 51 (* itor) -> DoProgress (valor); // 更新进度条 52 Itor ++ ; 53 } 54 } 55 };
- Adición de una clase base abstracta IProgress, a partir de la notificación original del control en una notificación específica mecanismo abstracto
- Generalmente no se recomienda C ++ admite la herencia múltiple, pero puede conducir a problemas de acoplamiento,
- Sólo en un caso con la recomendación, es decir, la clase derivada de la clase padre es un primario (Form1), o otras interfaces son de clase base abstracta (IProgress)
- Después de la reconstitución, las clases FileSplitter ya no están acoplados interfaz de clases (la ProgressBar), para lograr una compilación separada, en línea con la Dependencia Inversion Principio
- El futuro puede ser colocado en la interfaz de Windows, Linux o ejecutar la interfaz, la función de notificación de horarios dependen de la finalización de IProgress abstracta
- Formalmente, DoProgress () de la línea FileSplitter1.cpp 23, y se trasladó a la línea 28 MainForm2.cpp
- Utilizando el contenedor, que soporta una pluralidad de observadores (línea de comandos, la interfaz gráfica de usuario, etc.), la escritura FileSplitter constructor de la clase se cambia
- proceso de reconstrucción
- ProgressBar * m_progressBar; // Controles aviso específico
- IProgress * m_iprogress; // mecanismo de notificación abstracta
- List <IProgress *> m_iprogressList; // Ayuda múltiples observadores
resumen
- Diagrama de clases, Observador equivalente IProgress, Actualización corresponde DoProgress (), Asunto y ConcreteSubject FileSplitter equivalente, Adjuntar () correspondiente a addIProgress (), Notify () correspondiente a onProgress (), ConcreteObserver MainForm equivalente y ConsoleNotifier
- Asunto y Observador son estables, ConcreteSubject y ConcreteObserver están cambiando
- patrón Observer de manera que podemos cambiar independientemente la diana y el observador, de modo que la relación de dependencia entre los dos está acoplado libremente
- Cuando el destino envía una notificación sin especificar el espectador, la notificación se propagará de forma automática (no se sabe quién es el observador)
- El espectador decidir si para suscribirse a notificaciones, el público no sabía nada de
- marco UI modelo Observador se basa en el caso de un patrón muy común, es una parte importante del patrón MVC