singleCall單來源調用解析及實現

定義:

單來源調用指一個類的生成工做只能由特定類來執行。java

eg李寧牌鞋子只能由李寧專賣店生產git

 

這個問題歸結起來,也就是說在工廠模式中,指定的產品類只能經過具體的特定工廠類來生成,而不能本身new出來或者經過其餘類生成。github

具體的,咱們就在代碼實現中進行說明了。設計模式

這裏咱們來一步一步分析。函數

首先,一個類實例(對象)不能本身產生,那麼。咱們就須要屏蔽構造函數了。this

那麼,屏蔽了構造函數以後,如何獲取一個實例呢。spa

有兩種方案能夠實現。設計

方案一:

經過繼承獲取構造函數執行權限。如代碼指針

class base { protected: base() { Trace(""); } }; class driver:protected base { public: void test() { base b; } }; int main(int argc, char const *argv[]) { driver d; d.test(); return 0; }

這個方案只是可讓一個類可以產生實例。單他和咱們的意圖嚴重偏離:code

a實例和子類的生命週期一致。

b沒有自主權。

c其餘類也能夠模擬他的實現,繼承父類獲取生成權,這顯然是個垃圾方案。

方案二:相似單例模式方法處理

產品類 構造函數屏蔽,可是提供一個獲取實例的共有方法

靜態方法獲取實例 class base { protected: base() { Trace(""); } public: static base* getInstance(); }; base* base::getInstance() { return new base(); } int main(int argc, char const *argv[]) { // base* p = new base();
    base * p = base::getInstance(); return 0; }

經過方案二,咱們實現了一個類不能本身執行 base *p = new base()

類型綁定

那麼下面咱們的目標就是將這個產品類和具體可生產者進行綁定了。

如何綁定呢,對於一個特定的類,處理之,咱們就想到了this指針

因此咱們要作的就是,產品類構造函數依賴工廠類的this 指針

// 經過靜態方法獲取,且依賴driver的this指針。 // 可是此時也能夠經過臨時對象driver生成
class driver; class base { protected: base()//driver*)
 { Trace(""); } public: static base* getInstance(driver*); }; base* base::getInstance(driver*) { return new base(); } class driver { public: base* getInstance() { return base::getInstance(this); } }; int main(int argc, char const *argv[]) { base * p = (driver()).getInstance(); //咱們所指望的運行方式。
    p = base::getInstance(new driver()); //產品類抓住漏洞強行生成自我
    return 0; }

到這裏,貌似咱們的目標已經達到了,可是呢。如例子中的  p = base::getInstance(new driver());這個方法,本質仍是base類自主生成的。

並不能符合咱們的要求。

那麼到這裏,咱們應該如何處理呢。

我能想到的就是,不光讓base創建依賴driver的this指針,同時設置權限。才能執行getinstace()

首先給出最終代碼了

// 抽象接口類,提供子類行爲,同時定義權限值以及權限判斷給base中的getinstace方法使用
class abstractDriver { protected: bool _canCreate; abstractDriver(bool can) :_canCreate(can) {} public: virtual bool canCreate(){ return _canCreate; } }; class base { protected: base() { Trace(""); } public: static base* getInstance(abstractDriver*); }; // 根據依賴的this對應類是否有權限執行決定生成
base* base::getInstance(abstractDriver*dr) { if (dr->canCreate()) /* code */
        return new base(); else
        return NULL; } class driver:public abstractDriver { public: driver() :abstractDriver(false) { Trace(""); } //在獲取base實例先後修改權限。保證外部權限始終僞假
    base* getInstance() { _canCreate = true; base* p =base::getInstance(this); _canCreate = false; return p; } }; int main(int argc, char const *argv[]) { base* p = base::getInstance(new driver()); cout << p <<endl;    //NULL,未生成實例
    p = (driver()).getInstance(); cout << p <<endl; p = (driver()).getInstance(); cout << p <<endl; return 0; }

好了,最終的實現版本就完成了。

符合咱們的目標

base類只能經過driver類生成。

 

最後,咱們能夠發現,這個實現中的getInstace方法讓咱們想到了單例模式的實現。

不一樣的是單例模式的結果是最終

a只有一個類型實例產生,

b生成方式能夠是自主的 base::getinstance()

而咱們的單來源調用,

a。生成實例個數不必定是一個,只是生成方式限定了

b。不能經過直接調用base::getinstance()生成。

之因此拿出來將兩個模式進行比較,是由於:單來源調用並非23種設計模式中的一種,初次看他時,我本身也是一臉矇蔽。其次,二者都是很重要,很經常使用的方法。

我的源碼實現github地址:https://github.com/langya0/design_pattern_study/tree/master/singleCall

23種設計模式C++實現及擴展代碼:https://github.com/langya0/design_pattern_study

參考《Single Call 模式

相關文章
相關標籤/搜索