目錄
原型模式(Prototype Pattern)
優缺點
使用場景
注意事項
代碼實現
原型模式(Prototype Pattern)
????????原型模式(Prototype Pattern)是用于創建重復的對象,同時又能保證性能。這種類型的設計模式屬于創建型模式,它提供了一種創建對象的最佳方式之一。
????????這種模式是實現了一個原型接口,該接口用于創建當前對象的克隆。當直接創建對象的代價比較大時,則采用這種模式。例如,一個對象需要在一個高代價的數據庫操作之后被創建。我們可以緩存該對象,在下一個請求時返回它的克隆,在需要的時候更新數據庫,以此來減少數據庫調用。
優缺點
(1)優點:性能提高,當創建對象需要一系列繁瑣操作的時候,使用原型模式可以提高一定的性能。
(2)缺點:
- 配備克隆方法需要對類的功能進行通盤考慮,這對于全新的類不是很難,但對于已有的類不一定很容易,特別當一個類引用不支持串行化的間接對象,或者引用含有循環結構的時候。
- 必須實現 clone()接口。
使用場景
- 資源優化場景。
- 類初始化需要消化非常多的資源,這個資源包括數據、硬件資源等。
- 性能和安全要求的場景。
- 通過 new 產生一個對象需要非常繁瑣的數據準備或訪問權限,則可以使用原型模式。
- 一個對象多個修改者的場景。
- 一個對象需要提供給其他對象訪問,而且各個調用者可能都需要修改其值時,可以考慮使用原型模式拷貝多個對象供調用者使用。
- 在實際項目中,原型模式很少單獨出現,一般是和工廠方法模式一起出現,通過 clone 的方法創建一個對象,然后由工廠方法提供給調用者。原型模式已經與 Java 融為渾然一體,大家可以隨手拿來使用。
注意事項
???????與通過對一個類進行實例化來構造新對象不同的是,原型模式是通過拷貝一個現有對象生成新對象的。
深拷貝與淺拷貝
GO語言中的傳遞都是值傳遞,傳遞一個對象,就會把對象拷貝一份傳入函數中,傳遞一個指針,就會把指針拷貝一份傳入進去。賦值的時候也是這樣,ptObj := *pt 就會把傳遞的 Prototype 對象拷貝一份,如果是 ptObj := pt 的話,那么拷貝的就是對象的指針了.
而深拷貝和淺拷貝也可以這樣理解:
深拷貝就是拷貝整個對象,源對象和拷貝對象沒有任何關聯,也不會受到任何影響
淺拷貝就是拷貝對象指針,其實是引用地址都一樣,所以屬于牽一發動全身
注意: golang完全是按值傳遞,所以如果深度拷貝的對象中包含有指針的話,那么深度拷貝后,這些指針也會相同,會導致部分數據共享。
代碼實現
package mainimport "fmt"// 簡歷類,里面包含簡歷的基本信息
type Resume struct {name stringage int64sex stringcompany stringexperience string
}// 設置簡歷個人信息
func (r *Resume) setPersonInfo(name string, age int64, sex string) {r.name = namer.age = ager.sex = sex
}// 設置工作經驗
func (r *Resume) setWorkExperience(company string, experience string) {r.company = companyr.experience = experience
}// 顯示簡歷內容
func (r *Resume) display() {fmt.Printf("名字:%s,性別:%s,年齡:%d,工作單位:%s,工作經驗:%s \n", r.name, r.sex, r.age, r.company, r.experience)
}// 深拷貝,原型模式的核心
func (r *Resume) clone() *Resume {return &Resume{name: r.name,sex: r.sex,age: r.age,company: r.company,experience: r.experience,}
}
func main() {fmt.Println("---------------------------原簡歷")resume := &Resume{name: "李哈哈",sex: "男",age: 10,company: "*******責任公司",experience: "學武功和劃水、摸魚",}resume.display()fmt.Println("---------------------------簡歷副本")copyResume := resume.clone()copyResume.setPersonInfo("王嘻嘻", 21, "男")copyResume.display()
}