- 注意L缚觥I酌馈!碑韵! 如果你是技術大牛赡茸、技術大咖,請略過這篇文章避免耽擱您的時間祝闻,這篇文章屬于入門級別占卧。??
1、原型模式的概述:用原型實例對象指定創(chuàng)建對象種類联喘,并且通過拷貝這些原型創(chuàng)建新的對象(根據原始對象华蜒,Copy一個對象---Copy:淺拷貝和深度拷貝)
2、原型模式的使用場景:
- 當我們編寫組件需要創(chuàng)建新的對象豁遭,但又不需要依賴初始化操作(就像swift中的UIView組件)不依賴于構造器-->構造方法
- 初始化的過程需要消耗非常大的資源(數(shù)據資源:構造方法需要很多數(shù)據參數(shù)叭喜、硬件資源...)
原型模式的一些角色:克隆接口或者說協(xié)議(protocoltype抽象,相當于iOS中的NSCopying)蓖谢、具體的實現(xiàn)類(concreteType)捂蕴、客戶端(client),用一個簡單的實例(淺拷貝)理解一下
//淺拷貝協(xié)議
protocol ShallowCopyProtocal {
func clone() -> AnyObject?
}
//具體的實現(xiàn)類
class UserCopyModel: ShallowCopyProtocal {
var name:String?
var sex:String?
init(name:String,sex:String) {
self.name = name
self.sex = sex
}
func clone() -> AnyObject? {
return UserCopyModel(name:self.name!, sex:self.sex!)
}
}
//===========淺度拷貝測試===========
//原型對象
let user = UserCopyModel(name: "YSL", sex: "男")
//克隆對象
let copyUser:UserCopyModel = user.clone() as! UserCopyModel
//修改克隆對象的值,看看原型對象會不會改變
copyUser.name = "Andy"
copyUser.sex = "man"
print("原型對象:name = \(user.name!) sex= \(user.sex!)")
print("克隆對象:name = \(copyUser.name!) sex= \(copyUser.sex!)")
//打印結果如下
原型對象:name = YSL sex= 男
克隆對象:name = Andy sex= man
- 上面的實例拷貝的是值類型(直接拷貝數(shù)據)蜈抓,并不是引用類型启绰,所以不會改變原型對象值
再來看一下原型設計:數(shù)組的淺拷貝
protocol ShallowCopyProtocal {
func clone() -> AnyObject?
}
class TeacherModel {
var name:String?
init(name:String) {
self.name = name
}
}
class StudentCopyModel: ShallowCopyProtocal {
var name:String?
var teachers:Array<TeacherModel>?
init(name:String, teachers:Array<TeacherModel>) {
self.name = name
self.teachers = teachers
}
func clone() -> AnyObject? {
return StudentCopyModel(name: self.name!, teachers: self.teachers!)
}
}
//數(shù)組的淺拷貝測試
let array = [TeacherModel(name:"Jack"),TeacherModel(name:"Rose")]
let student = StudentCopyModel(name: "Mimi", teachers: array)
let copyStudent: StudentCopyModel = student.clone() as! StudentCopyModel
copyStudent.name = "DaChanglian"
copyStudent.teachers?[0].name = "Lisa"
print("原型對象:name = \(student.name!) teachers = \(String(describing: student.teachers![0].name))")
print("克隆對象:name = \(copyStudent.name!) teachers = \(String(describing: copyStudent.teachers![0].name))")
//輸出結果
原型對象:name = Mimi teachers = Optional("Lisa")
克隆對象:name = DaChanglian teachers = Optional("Lisa")
- 看到以上結果,應該明白沟使,數(shù)組是重新創(chuàng)建了委可,但是數(shù)組中保存的對象沒有重新創(chuàng)建(也就是說數(shù)組保存的是對象的引用類型,那么拷貝的時候拷貝的是數(shù)組的值,數(shù)組的值就是TeacherModel對象的引用)着倾。
- 這樣對數(shù)組中的對象重新賦值拾酝,其實是改變了對象的值。如何證明數(shù)組保存的是對象的引用卡者,直接打印數(shù)組就可以證明了蒿囤。打印結果如下:
print("原型對象:teachers = \(student.teachers!)\n克隆對象:teachers = \(copyStudent.teachers!)")
原型對象:teachers = [ArchitectGenerics.TeacherModel, ArchitectGenerics.TeacherModel]
克隆對象:teachers = [ArchitectGenerics.TeacherModel, ArchitectGenerics.TeacherModel]
如果遇到以上的問題,我們如何解決這樣的問題呢崇决?答案就是原型模式-->深度拷貝材诽。再看一個例子,解決一下這個問題??
//深度拷貝協(xié)議接口
protocol DeepCopyProtocal {
func deepClone() -> AnyObject?
}
//深度拷貝測試的具體類 老師類
class TeacherModel2: DeepCopyProtocal {
var name:String?
init(name:String) {
self.name = name
}
func deepClone() -> AnyObject? {
return TeacherModel2(name: self.name!)
}
}
//深度拷貝的測試類 學生類
class DeepCopyStudentModel: DeepCopyProtocal {
var name:String?
var teachers:Array<TeacherModel2>?
init(name:String, teachers:Array<TeacherModel2>) {
self.name = name
self.teachers = teachers
}
func deepClone() -> AnyObject? {
var newArray = Array<TeacherModel2>()
for teacher in self.teachers! {
newArray.append(teacher.deepClone() as! TeacherModel2)
}
return DeepCopyStudentModel(name: self.name!, teachers: newArray)
}
}
// ============ 深度拷貝測試===========
let array = [TeacherModel2(name:"Jack"),TeacherModel2(name:"Rose")]
let student = DeepCopyStudentModel(name: "Mimi", teachers: array)
let copyStudent: DeepCopyStudentModel = student.deepClone() as! DeepCopyStudentModel
copyStudent.name = "DaChangLian"
copyStudent.teachers?[0].name = "Lisa"
print("原型對象:name = \(student.name!) teachers = \(String(describing: student.teachers![0].name))")
print("克隆對象:name = \(copyStudent.name!) teachers = \(String(describing: copyStudent.teachers![0].name))")
//=========打印結果================
原型對象:name = Mimi teachers = Optional("Jack")
克隆對象:name = DaChangLian teachers = Optional("Lisa")
- 深度拷貝是重新拷貝對象(在調用deepCopy()方法的時候重新創(chuàng)建了新的對象),引用對象的值改變恒傻,不影響原型對象