functionによる設計の改善

1525 ワード

このような適用シーンには,AとBの2つのクラスがあり,BではAを呼び出す1つのメソッド(メンバ関数)が必要であると仮定する.では、私たちのコードはこのようなものかもしれません.
 
class A

{

public:

	void Func(void) 

	{ 

		printf("%s\r
", __FUNCTION__); } }; class B { public: void UseA() { a->Func(); } public: A* a; };

 
呼び出しコードは次のとおりです.
 
A a;

B b;

b.a = &a;

b.UseA();


 
 
上のコードを見て、何か問題があるか見てみましょう.
  • の2つのクラスの中でBはAに依存関係を生んで、これは少し不快です;
  • いつか私たちがAの代わりに別のクラスCを使いたいと思っているのは、Bを書き直すことを意味しています.これはもっと不快です.

  • 上記の2つの問題は実質的に結合の問題であり,依存関係は強い結合であり,結合度が高くなるとコード可読性とメンテナンス性が悪くなる.
     
    この2つのクラスの関係を解析し,BでAのメンバー関数を呼び出して依存を生じた.この呼び出しは完全に関数ポインタを使用することができ、C++の関数ポインタを使用するのは面倒なのでfunctionで代用します.改良されたBの定義は以下の通りである.
    class B
    
    {
    
    public:
    
    	std::function<void(void)>	AFunc;
    
    
    
    	void UseA(void) 
    
    	{ 
    
    		if(AFunc != NULL) AFunc(); 
    
    	}
    
    };
    
    

     
    呼び出し方法は以前とあまり差がなく、割り当て操作のオブジェクトをAのポインタからAのメンバー関数に変更しただけです.
    A a;
    
    B b;
    
    b.AFunc = std::bind(&A::Func, &a);
    
    b.UseA();
    
    

      
    コードは少し複雑に見えますが、コードロジックの観点から多くの改善があります.
  • BとAは完全にデカップリングされ、実行期間にBのオブジェクトのみがAのオブジェクトに依存し、この依存は呼び出し者の制御下に完全にある.
  • AをCに置き換えたいなら、交換して、呼び出しコードを変更すればいいです.Bの定義コードは1行も動かない--これは私たちが追求している柔軟性と拡張性です.
  • C c;
    
    b.AFunc = std::bind(&C::Func, &c);
    
    b.UseA();
    
    

     
      
    C++0 xの新しい特性としてstd::functionとstd::bindは現在VS 2010でのみサポートされており、他のコンパイラの学生はboostライブラリを代替案として使用することができ、使い方はまったく同じである.