[Design Mode] design patterns courses (four) - observer mode

Scenes

  • Observer / Event, are "Component Collaboration" model to solve the problem of collaboration and application framework
  • Motivation: In the software build process, the need to build certain objects of a "notice - dependencies", namely the state of an object (target object) is changed, all dependent objects (objects observer) will be notified If such a dependency too closely, the software will not be well to resist change
  • Object-oriented technology, this dependence may be weakened, dependency form a stable, reducing the coupling system software

Examples

MainForm1.cpp

 1 class MainForm : public Form
 2 {
 3     TextBox* txtFilePath;
 4     TextBox* txtFileNumber;
 5     ProgressBar* progressBar;
 6 
 7 public:
 8     void Button1_Click(){
 9 
10         string filePath = txtFilePath->getText();
11         int number = atoi(txtFileNumber->getText().c_str());
12 
13         FileSplitter splitter(filePath, number, progressBar);
14 
15         splitter.split();
16 
17     }
18 };
View Code

FileSplitter1.cpp

 1 class FileSplitter
 2 {
 3     string m_filePath;
 4     int m_fileNumber;
 5     ProgressBar* m_progressBar;
 6 
 7 public:
 8     FileSplitter(const string& 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 read the documents
 . 17  
18 is          // 2. small batches to write to the file 
. 19          for ( int I = 0 ; I <m_fileNumber; I ++ ) {
 20 is              // ... 
21 is              a float progressValue = m_fileNumber;
 22 is              progressValue = (I + . 1 ) / progressValue;
 23 is              m_progressBar-> the setValue (progressValue);
 24          }
 25  
26 is      }
 27 };
View Code
  • File splitter program for large files, we need to split the progress bar shows progress
  • MainForm1 two collecting user input parameters, is transmitted to FIleSplitter1
  • Question: violation of the Dependency Inversion Principle. Realization (FileSplitter) rely details (ProgressBar), and the details are likely to change (for example, a late switch to Label show progress, or no graphical interface in the Linux platform, with ... represent progress)
  • Dependence: refers to the level of compiler-dependent (A dependent B, A compile time needed to compile B)
  • Do not rely on the details, but depend on it abstract
  • ProgressBar control is a specific notification, is available in an abstract way (Interface IProgress) representation

MainForm2.cpp

 1 class MainForm : public Form, public IProgress
 2 {
 3     TextBox* txtFilePath;
 4     TextBox* txtFileNumber;
 5 
 6     ProgressBar* progressBar;
 7 
 8 public:
 9     void Button1_Click(){
10 
11         string filePath = txtFilePath->getText();
12         int number = atoi(txtFileNumber->getText().c_str());
13 
14         ConsoleNotifier cn;
15 
16         FileSplitter splitter(filePath, number);
17 
18         splitter.addIProgress(this); //订阅通知
19         splitter.addIProgress(&cn); //订阅通知
20 
21         splitter.split();
22 
23         splitter.removeIProgress(this);
24 
25     }
26 
27     virtual void DoProgress(float value){
28         progressBar->setValue(value);
29     }
30 };
31 
32 class ConsoleNotifier : public IProgress {
33 public:
34     virtual void DoProgress(float value){
35         cout << ".";
36     }
37 };
View Code

FileSplitter2.cpp

. 1  class IProgress {
 2  public :
 . 3      Virtual  void DoProgress ( a float value) = 0 ;
 . 4      Virtual ~ IProgress () {}
 . 5  };
 . 6  
. 7  class FileSplitter
 . 8  {
 . 9      String m_filePath;
 10      int m_fileNumber;
 . 11  
12 is      List <IProgress *> m_iprogressList; // abstract notification mechanism to support a plurality of observers 
13 is      
14  public :
 15      FileSplitter ( const  StringFilePath &, int filenumber):
 16          m_filePath (filePath), 
 . 17          m_fileNumber (filenumber) {
 18 is  
. 19      }
 20 is  
21 is      void Split () {
 22 is  
23 is          // 1. large file read
 24  
25          @ 2 to small batches writing file 
26 is          for ( int I = 0 ; I <m_fileNumber; I ++ ) {
 27              // ... 
28  
29              a float progressValue = m_fileNumber;
 30              progressValue = (I + . 1 ) /pro gre ssValue;
31              onProgress (pro gre ssValue); // 发送通知
32          }
 33  
34      }
 35  
36  
37      void addIProgress (* Progress Progress) {
 38          m_iprogressList.push_back (PROGRESS);
39      }
 40  
41      void removeIProgress (* Progress Progress) {
 42          m_i pro gre Asli st.remove (PROGRESS);
43      }
 44  
45  protected :
 46      virtual  void onProgress ( float value) {
47         
48         List<IProgress*>::iterator itor=m_iprogressList.begin();
49 
50         while (itor != m_iprogressList.end() )
51             (*itor)->DoProgress(value); //更新进度条
52             itor++;
53         }
54     }
55 };
View Code
  • Adding an abstract base class IProgress, from the original notification of control into a specific notification mechanism abstract
  • c ++ supports multiple inheritance, but can lead to coupling problems, is generally not recommended
  • Only in one case with the recommendation, i.e. the parent class derived class is a primary (Form1), or other interfaces are abstract base class (IProgress)
  • After reconstitution, FileSplitter classes are no longer coupled interface classes (the ProgressBar), to achieve a separate compilation, in line with the Dependency Inversion Principle
  • The future can be placed in the Windows interface, or run Linux interface, schedule notification function dependent on the completion of abstract IProgress
  • Formally, DoProgress () from the line FileSplitter1.cpp 23, and moved to the line 28 MainForm2.cpp
  • Using the container, supporting a plurality of observers (command line, the GUI, etc.), writing FileSplitter class constructor is changed
  • Reconstruction process
    • ProgressBar * m_progressBar; // specific notice Controls
    • IProgress * m_iprogress; // abstract notification mechanism
    • List <IProgress *> m_iprogressList; // support multiple observers

to sum up

  • Class diagram, Observer equivalent IProgress, Update corresponds DoProgress (), Subject and ConcreteSubject equivalent FileSplitter, Attach () corresponding to addIProgress (), Notify () corresponding to onProgress (), ConcreteObserver equivalent MainForm and ConsoleNotifier
  • Subject and Observer are stable, ConcreteSubject and ConcreteObserver are changing
  • Observer pattern so that we can independently change the target and the observer, so that the dependence relationship between the two is loosely coupled
  • When the target sends a notification without specifying the viewer, notification will automatically propagate (do not know who the observer)
  • The viewer to decide whether to subscribe to notifications, audience knew nothing about
  • Observer model is based UI framework in the event a very common pattern, is an important part of the MVC pattern

Guess you like

Origin www.cnblogs.com/cxc1357/p/12288002.html