观察者模式

在软件实现过程中,一个对象的状态发生改变所依赖的对象都须得到通知需要通知,但这种依赖不能过于紧密,需要抵御变化,

通过实现进度条的伪码来实现

 

该MainForm1.cpp中通过实现具体的进度条代码,来达到需求,如果需求改变,则需要在源码中所需位置依次增加所需代码

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 };

 

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 
15     void split(){
16 
17         //1.读取大文件
18 
19         //2.分批次向小文件中写入
20         for (int i = 0; i < m_fileNumber; i++){
21             //...
22             float progressValue = m_fileNumber;
23             progressValue = (i + 1) / progressValue;
24             m_progressBar->setValue(progressValue);
25         }  
26 
27     }  
28 };

 

 

 

MainForm2.cpp

class MainForm : public Form, public IProgress                                
{
    TextBox* txtFilePath;
    TextBox* txtFileNumber;

    ProgressBar* progressBar;

public:
    void Button1_Click(){

        string filePath = txtFilePath->getText();
        int number = atoi(txtFileNumber->getText().c_str());

        ConsoleNotifier cn;

        FileSplitter splitter(filePath, number);

        splitter.addIProgress(this); //订阅通知
        splitter.addIProgress(&cn); //订阅通知

        splitter.split();

        splitter.removeIProgress(this);

    }  

    virtual void DoProgress(float value){
        progressBar->setValue(value);
    }  
};

class ConsoleNotifier : public IProgress {
public:
    virtual void DoProgress(float value){
        cout << ".";
    }  
};

通过在父类中声明一个纯虚函数,以指针的形式实现多态可以通过不同的数据结构实现多个通知,可根据各种不同需求在子类中(DoProgress())中实现具体的功能。

FileSplitter2.cpp

 1 class IProgress{                                                              
 2 public:
 3     virtual void DoProgress(float value)=0;
 4     virtual ~IProgress(){}
 5 };
 6 
 7 
 8 class FileSplitter
 9 {
10     string m_filePath;
11     int m_fileNumber;
12 
13     List<IProgress*>  m_iprogressList; // 抽象通知机制,支持多个观察者
14     
15 public:
16     FileSplitter(const string& filePath, int fileNumber) :
17         m_filePath(filePath), 
18         m_fileNumber(fileNumber){
19 
20     }  
21 
22 
23     void split(){
24 
25         //1.读取大文件
26 
27         //2.分批次向小文件中写入
28         for (int i = 0; i < m_fileNumber; i++){
29             //...
30 
31             float progressValue = m_fileNumber;
32             progressValue = (i + 1) / progressValue;
33             onProgress(progressValue);//发送通知
34         }  
35 
36     }  
37 
38 
39     void addIProgress(IProgress* iprogress){
40         m_iprogressList.push_back(iprogress);
41     }  
42 
43     void removeIProgress(IProgress* iprogress){
44         m_iprogressList.remove(iprogress);
45     }  
46 
47 
48 protected:
49     virtual void onProgress(float value){
50     
51         List<IProgress*>::iterator itor=m_iprogressList.begin();
52 
53         while (itor != m_iprogressList.end() )
54             (*itor)->DoProgress(value); //更新进度条
55             itor++;
56         }  
57     }  
58 };

 

 

 

单继承一个父类,多继承其他接口

不推荐大括号换行,这个增加了语法分析时间复杂度,扫描时要去掉回车换行符

posted @ 2021-02-07 23:53  miaorn  阅读(82)  评论(0编辑  收藏  举报