Monday, January 30, 2012

Proxy -- Hiding Implementation Details From Interface (C++)

"Separating interface from implementation and hiding implementation details"是我閱讀OOP到現在不斷提到的概念,基於一層層往上架構、每階層對上密封,只提供使用界面(interface),至於內部如何完成則加以密封,不需要也不該讓使用的人看到。

Write C++ Code in Multi-files提到把C++程式分到不同檔案,來使得implementation和interface分離,然而會發現到在interface中仍然可以看到private variables之類應該密封的程式碼,所以我們透過"Proxy Class"來近一步把該密封的東西分到不同檔案中。

我們把應該密封的東西都先寫到另一個header裡面(這裡稱Implementation.h)
Implementation.h
class Implementation{
 public:
  Implementation(int new_value)
   :value(new_value){
  }

  void setValue(int new_value){
   value = new_value;
  }

  int getValue(){
   return value;
  }

 private:
  int value;
};

然後透過"forward class declaration"的方式去連結原本的interface,即我們在原本的header(這裡稱Interface.h)中定義了Implementation的prototype,然後用pointer的方法將原本class定義中該密封的東西指向到Implementation,達到密封的效果。
Interface.h
class Implementation;//forward class declaration for Implementation.h

class Interface{
 public:
  Interface(int);
  ~Interface();
  void setValue(int);
  int getValue();
 private:
  Implementation *ptr;
};

至於Inferface.cpp中需要透過pointer指向的方式返回呼叫Implementation中密封的functions。
#include "Interface.h"
#include "Implementation.h"

Interface::Interface(int value)
 : ptr(new Implementation(value)){
}

Interface::~Interface(){
 delete ptr;
}

void Interface::setValue(int value){
 ptr->setValue(value);
}

int Interface::getValue(){
 ptr->getValue();
}

這些過程對於上一層的使用者(main)是沒有差別的。
#include <iostream>
#include "Interface.h"

using namespace std;

int main(){

 Interface a(19);

 cout << "Value >> " << a.getValue() << endl;

 a.setValue(13);

 cout << "Value >> " << a.getValue() << endl;

 return 0;
}

Output:
Value >> 19
Value >> 13