多態、策略模式和簡單工廠模式的理解

        最近在看設計模式一本書,發現策略模式和簡單工廠模式很像,剛剛開始我還以爲是一樣的,總感覺沒什麼區別,後來纔看明白,有一點點個人的理解,記錄下來,方便下次複習以及理解。

概念理解:

多態:C++的多態性用一句話概括就是,在基類的函數前加上virtual關鍵字,在派生類中重寫該函數,運行時將會根據對象的實際類型來調用相應的函數。如果對象類型是派生類,就調用派生類的函數;如果對象類型是基類,就調用基類的函數


策略模式:定義了實現,用接口來封裝起來,通過構造器的構造參數不同使得實現有所不同。


簡單工廠模式:定義了實現,用接口來封裝起來,由一個工廠類根據傳入的參數,動態決定應該創建哪一個產品類(這些產品類繼承自一個父類或接口)的實例。

代碼例子:

多態:

class classA
{
public:
    classA();
    virtual void test();
};

class classB : public classA
{
public:
    classB();
    void test();
};

classA::classA()
{
}
void classA::test()
{
    printf("classA test Func\n");
}

classB::classB()
{
}

void classB::test()
{
    printf("classB test Func\n");
}

測試代碼:

int main(int argc, char*argv[])
{
    classA *pBaseClass = new  classA();
    pBaseClass->test(); //輸出結果是 : classA test Func

    classB *pSubClass = new classB();
    pSubClass->test(); //輸出結果是 classB test Func

    classA *pData = new  classB();
    pData->test(); //輸出結果是 classB test Func 
	
    return 0;
}

注意:爲什麼一定要加virtual纔有多態的效果,因爲不加virtual 的話 編譯器在編譯的時候,就已經確定了對象調用的函數的地址,要解決這個問題就要使用遲綁定(late binding)技術。當編譯器使用遲綁定時,就會在運行時再去確定對象的類型以及正確的調用函數。而要讓編譯器採用遲綁定,就要在基類中聲明函數時使用virtual關鍵字(注意,這是必須的,很多學員就是因爲沒有使用虛函數而寫出很多錯誤的例子),這樣的函數我們稱爲虛函數。一旦某個函數在基類中聲明爲virtual,那麼在所有的派生類中該函數都是virtual,而不需要再顯式地聲明爲virtual。

策略模式:

class compositor
{
public:
    compositor();
    virtual void compose();
};

class compositorA : public compositor
{
public:
    compositorA();
    void compose();
};

class compositorB : public compositor
{
public:
    compositorB();
    void compose();
};

class compsotion
{
public:
    compsotion(compositor* p);
    void test();
private:
    compositor* pDate;
};
compositor::compositor()
{
}
void compositor::compose()
{
    printf("compositor compose Func ");
}

compositorA::compositorA()
{
}
void compositorA::compose()
{
    printf("compositorA compose Func ");
}

compositorB::compositorB()
{
}
void compositorB::compose()
{
    printf("compositorB compose Func ");
}

compsotion::compsotion(compositor* p):pDate(p)
{

}

void compsotion::test()
{
    pDate->compose();
}
測試代碼如下:
int main(int argc, char* argv[])
{
    int i = 2;
    compsotion * pComposition;

    switch(i){
    case 3:
        pComposition = new compsotion(new compositorB());
        break;
    case 2:
        pComposition = new compsotion(new compositorA());
        break;
    case 1:
        pComposition = new compsotion(new compositor());
        break;
    default:
        retuan 0;
    }
    pComposition->test();  
	
	return 0;
}
輸出結果: 
	compositorA compose Func
當我們改變i的值,會進入不同的處理函數。

簡單工廠模式:

class AbsClass
{
public:
       AbsClass();
       virtual void test();
};


class ClassA:public AbsClass
{
public:
       ClassA();
       void test();
};

class ClassB:public AbsClass
{
public:
       ClassB();
       void test();
};

class CSimpleFactory
{
public:
    CSimpleFactory();
    static AbsClass* createClass(int type);
};

CSimpleFactory::CSimpleFactory()
{
}
AbsClass* CSimpleFactory::createClass(int type)
{
    AbsClass *cs = NULL;
    switch(type){
    case 1:
        cs = new AbsClass();
        break;
    case 2:
        cs = new ClassA();
        break;
    case 3:
        cs = new ClassB();
        break;
    default:
        break;
    }
    return cs;
}

AbsClass::AbsClass()
{
}
void AbsClass::test()
{
    printf("AbsClass::test\n");
}

ClassA::ClassA()
{
}
void ClassA::test()
{
    printf("ClassA::test\n");
}

ClassB::ClassB()
{
}
void ClassB::test()
{
    printf("ClassB::test\n");
}
測試代碼如下:
int main(int argc, char*argv[])
{

    int i = 2;
    AbsClass* pDate = CSimpleFactory::createClass(i);
	if(pDate)
		pDate->test();

    return 0;
}
輸出結果: ClassA::test  當改變條件type時,會得到不同行爲的對象,當然也就會有不同的行爲了。

總結:

        策略模式和簡單工廠模式看起來非常相似,都是通過多態來實現不同子類的選取,這種思想從剛剛的例子中也可以看出來。如果從使用這兩種模式的角度來看的話,我們會發現在簡單工廠模式中我們只需要傳遞相應的條件就能得到想要的一個對象,然後通過這個對象實現算法的操作。而策略模式,使用時必須首先創建一個想使用的類對象,然後將該對象最爲參數傳遞進去,通過該對象調用不同的算法。在簡單工廠模式中實現了通過條件選取一個類去實例化對象,策略模式則將選取相應對象的工作交給模式的使用者,它本身不去做選取工作。簡單理解爲策略模式使用前需要知道具體某一個對象,簡單工廠則是通過條件創造對象,兩者都是通過多態調用具體算法。


發佈了36 篇原創文章 · 獲贊 158 · 訪問量 29萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章