デザインパターンの理解:オブザーバーパターン

    オブザーバーモデル、オブジェクト動作モデル、依存関係モデル、パブリッシュ/サブスクライブモデルとも呼ばれます。オブジェクトの状態が変化すると、それに依存する複数のオブジェクトが通知を通じて自動的に更新されます。たとえば、JAVAのリスナー、C#のイベント。 

    合理的な依存関係では、下位の構造が上位の構造に依存してはなりませんただし、場合によっては、最上位のオブジェクトを最下位のメソッドから更新する必要があります。一般的な解決策は、上位層のオブジェクトをパラメータの形式で下位層に継続的に渡すことです。オブザーバーモードでは、通知は最下位層のメソッドでインターフェイスに送信され、上位層のオブジェクトはコンテンツを次のように更新します。インターフェイスの実装によるその属性。

    この場合、大きなファイルをコピーするときにプログレスバーを更新する必要があります。

class FileCopy{
   string srcpath;
   string dispath;
   ProgressBar * progressBar;
   public:
   FileCopy(string s,string d,ProgressBar & p):filepath(s),dispath(d),progressBar(p){}
   void copy(){
     //1 创建目标文件,读取源文件
     disfile =createfile(dispath)
     srcfile =readfile(srcpath)
     
     ....
     double totalsize = srcfile.totalsize();
     double sum = 0;
     while(content=srcfile.readline()){
        //按行写入文件
        disfile.write(content);
        //写文件后更新进度条
        sum +=content.size;
        progressBar->setvalue(sum/totalsize);
     }
   }
}

//------------界面---------------
class MainForm {
ProgressBar  bar;
public:
 void button_Click(){ 
    //.....
    FileCopy fc(srcfile,disfile,&bar);
    fc.copy();
 }
}

上記のコード設計では、機能は実現されていますが、欠点は明らかです。

1.下位層のFileCopyは、上位メインフォームのオブジェクトに依存します。FileCopyクラスは、コンソール、Webページなどの他のプロジェクトで再利用することはできません。

2.要件が「プログレスバーを使用して進行状況を表示しない、ラベルを使用して進行状況をパーセンテージで直接表示する」になる場合、オブジェクトタイプを上から下に変更する必要があり、progressBarにはsetvalueメソッドがあります。他のコントロールはそうではないかもしれません。変換は非常に複雑です。

3.現在、このメソッドは1つのプログレスバーのみをサポートしています。複数の異なるコントロールをサポートする場合は、パラメーターを拡張することしかできず、保守性が低下します。

次のコードでは、オブザーバーパターンのパターンデザインが同じ要件を実現していることを示しています。最下層の最上層への依存を取り除き、安定性と変化の分離を実現し、クラスとインターフェースを他のプロジェクトでそのまま使用できます。改善されたコードの再利用性、簡単なメンテナンス、および簡単なスケーラビリティ。通知の形式で、通知インターフェイスが開かれ、アプリケーションがインターフェイスを実装して、進行状況バーを更新する目的を達成できるようにします。

//通知接口
class INotice{
    virtual void notify(double)=0;
}
class FileCopy{
   string srcpath;
   string dispath;
   vector<INotice*> notices; //通知对象集合
   public:
   FileCopy(string s,string d):filepath(s),dispath(d){}
   void add(INotice * in){notices.push_back(in);}
   void copy(){
     //1 创建目标文件,读取源文件
     disfile =createfile(dispath)
     srcfile =readfile(srcpath)
     
     ....
     double totalsize = srcfile.totalsize();
     double sum = 0;
     while(content=srcfile.readline()){
        //按行写入文件
        disfile.write(content);
        //写文件后更新进度条
        sum +=content.size;
        //给所有依赖发出通知
        copynotify(sum/totalsize);
     }
   }
   protected:
   void copynotify(double value){
      for(notice :notices){
        notice->notify(value);
      }
   }
}

//------------界面,实现INotice接口方法---------------
class MainForm:public INotice{
ProgressBar  bar;
public:
 void button_Click(){ 
    //.....
    ChildForm *cform = new ChildForm ();
    FileCopy fc(srcfile,disfile);
    
    fc.add(this);
    fc.add(cform );
    fc.copy();
 }
 virtual void notify(double value){
   bar.setvalue(value);
 }
}

class ChildForm:public INotice{
    Label   label;
    virtual void notify(double value){
       bar.settitle(value);
    }
}

 

 

おすすめ

転載: blog.csdn.net/superSmart_Dong/article/details/114108125