1. 程式人生 > >巧用NULL模式解耦依賴

巧用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();

}