2014-02-27 76 views
4
 /** 
    * A JavaScript value representing a signed integer. 
    */ 
    class V8_EXPORT Integer : public Number { 
    public: 
     static Local<Integer> New(Isolate* isolate, int32_t value); 
     static Local<Integer> NewFromUnsigned(Isolate* isolate, uint32_t value); 
     int64_t Value() const; 
     V8_INLINE static Integer* Cast(v8::Value* obj); 
    private: 
     Integer(); 
     static void CheckCast(v8::Value* obj); 
    }; 

上述代碼來自Google的V8引擎。這個例子初始化:爲什麼Google不希望您使用C++構造函數?

Handle<Value> x = Integer::New(42); 

從我可以在源代碼中看到,它們標誌着構造爲私有,並希望您能夠使用新的函數來創建該類的實例。這不符合標準的C++設計模式嗎?爲什麼他們不是隻爲構造函數重載而不是創建靜態函數?當人們試圖將圖書館從一種語言移植到另一種語言時,這通常是你看到的那種事情(我現在唯一能想到的就是Xamarin的iOS工具包)。

我試着谷歌周圍的這種類型的約定名稱,但無法找到真正的任何東西。

+0

可能是因爲(這裏瘋狂猜測)整數和其他原始相關類型經常合併以避免不斷創建值? – njzk2

+2

還要注意,工廠方法返回的是一個不同於'new Integer(42)'返回的類型。考慮一下。 – vanza

+3

這種技術通常被稱爲「命名構造函數成語」(因爲你的(命名的)靜態成員函數有效地替換了構造函數,在這種情況下,查看返回類型'New',它不返回'Integer',它返回一個Local '這是因爲他們需要確保它可以映射到它所表示的JavaScript,所以需要一些額外的簿記,並且這是作爲整數的包裝來實現的 – jalf

回答

3

這是一種稱爲「靜態工廠方法」的模式,由Joshua Bloch推薦爲「Effective Java」中的第1項。 (我幾乎可以肯定,Scott Myers在「Effective C++」中有一個相同的項目,但現在我沒有該書的副本來檢查。)

通過這種方法創建對象的好處,而不是正常的構造中,通過布洛赫描述:

  • 這樣的方法可以具有描述性名稱
  • 不像構造,這樣的方法是不需要創建一個全新的對象,即,它們可以返回以前緩存的副本 的對象。
  • 不像構造,這樣的方法也可以返回其返回類型的任何亞型的一個目的
  • 這樣的方法減少的參數化對象的構造的詳細程度

還有一些缺點,以這種設計模式,它是隻有在某些情況下的建議。

在V8的情況下,列表中的第二點可能是最重要的,以加速施工。我不是V8專家,但似乎「事件驅動,單線程」是它的哲學。當許多「事件回調」想要有一個相同的號碼時,他們都會得到該號碼的同一個實例的副本。

2

有兩種類型的手柄。其中之一是「本地」處理。如代碼所示,本地句柄的類別爲Handle<SomeType>

https://developers.google.com/v8/embed

注:手柄堆棧不是C++調用棧的一部分,但 手柄範圍被嵌入在C++堆棧。處理範圍只能是 堆棧分配,不能與新分配。

https://developers.google.com/v8/get_started

  • 手柄是指向的對象。所有V8對象都使用句柄​​訪問,因爲V8垃圾收集器工作的方式,所以它們是必需的。
1

看起來就像他們正在使用靜態工廠方法。當你想集中創建對象時這是有意義的,因爲它必須以特殊的方式完成。我可以想象,構造函數提供了一個普通的有效整數對象,並且工廠方法比調用其他方法將對象帶入特殊的初始狀態。

限制構造函數儘可能最小也是一個好主意。建設者應該建立類的不變性。其他設置可以通過特殊的方法來完成,並且特定的初始化對象的創建可以封裝在工廠中。

+0

好的一般性猜測,但恐怕這個問題對於google的[tag:v8]非常具體。 –

1

使用工廠方法從低級別C++構造函數中抽象出來的最重要原因是分配和構造需要在此API中進行組合。大多數工廠方法執行分配。但是,這種分配必須發生在(垃圾回收)JavaScript堆上,而不是C++堆中。這有幾個後果:

  1. 我們不能讓構建原始對象,而不分配,例如在堆棧上。

  2. 我們不能允許使用C++端new

  3. 我們不能默認使用原始指針,因爲這會破壞垃圾回收(句柄是GC知道的一個間接尋址,並且可以針對重定位進行更新)。

工廠方法有助於實施這些限制。

相關問題