巧用NULL模式解耦依賴
1. 初始
應用A和應用B均用到了庫libX.a中的類class A:
由於需求的變化,應用B需要庫libM.a的能力,以便和服務M互動。為了複用和簡化,通過類A間接提供,應用B不用修改程式碼,只需要重新編譯即可獲得新的能力,其它用到類A的應用也是如此。
這個時候會產生一個問題,會導致應用A的Makefile也需要指定庫libZ.a,否則編譯時會報庫libZ.a中的符號找不到錯誤。
需要一種方法來解除應用A對庫libZ.a的依賴。
2. 方法一:使用巨集限定庫libZ.a
這個方法要求類A全標頭檔案方式,不能有.cpp檔案,因為需要分別在編譯應用A和應用B時選擇性開啟對庫libZ.a的依賴。
這個方法雖然解決了問題,但是應用B得修改,需要增加開啟巨集的程式碼,其它有類似需求的應用均需要如此操作,涉及修改面比較大。
3. 方法二:使用NULL模式
這種方法擴充套件性更好,新增其它的依賴也能應付,已有或不需要新特性的完全不需要修改,編譯不受影響,不會被迫依賴libM.a。
class IX { public: virtual ~IX() {} virtual void method1() = 0; virtual void method2() = 0; };
class CNullX: public IX { private: virtual void method1() { /* 什麼都不做 */ } virtual void method2() { /* 什麼都不做 */ } };
class CMX: public IX { private: virtual void method1() { // 呼叫libM.a和Server M互動 }
virtual void method2() { // 呼叫libM.a和Server M互動 } };
// 原類A class A { public: // 新增預設引數x,並保持和原相容 A(IX* x=NULL) { _x = (x != NULL)? x: new CNullX; }
virtual ~A() { delete _x; }
public: void method1() { _x->method1(); }
void method2() { _x->method2(); }
private: IX* _x; };
// 對於應用A,不用修改任何程式碼,而且編譯時不需要依賴libM.a // 對於應用B,需要微修改,並編譯時指定庫libM.a和Server void ApplicatonB::f() { CMX* x = new CMX; A a(x); a.method1(); } |