- 注意!!!! 如果你是技術(shù)大牛、技術(shù)大咖,請(qǐng)略過這篇文章避免耽擱您的時(shí)間,這篇文章屬于入門級(jí)別。??
1、原型模式的概述:用原型實(shí)例對(duì)象指定創(chuàng)建對(duì)象種類,并且通過拷貝這些原型創(chuàng)建新的對(duì)象(根據(jù)原始對(duì)象,Copy一個(gè)對(duì)象---Copy:淺拷貝和深度拷貝)
2、原型模式的使用場(chǎng)景:
- 當(dāng)我們編寫組件需要?jiǎng)?chuàng)建新的對(duì)象,但又不需要依賴初始化操作(就像swift中的UIView組件)不依賴于構(gòu)造器-->構(gòu)造方法
- 初始化的過程需要消耗非常大的資源(數(shù)據(jù)資源:構(gòu)造方法需要很多數(shù)據(jù)參數(shù)、硬件資源...)
原型模式的一些角色:克隆接口或者說協(xié)議(protocoltype抽象,相當(dāng)于iOS中的NSCopying)、具體的實(shí)現(xiàn)類(concreteType)、客戶端(client),用一個(gè)簡(jiǎn)單的實(shí)例(淺拷貝)理解一下
//淺拷貝協(xié)議
protocol ShallowCopyProtocal {
func clone() -> AnyObject?
}
//具體的實(shí)現(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!)
}
}
//===========淺度拷貝測(cè)試===========
//原型對(duì)象
let user = UserCopyModel(name: "YSL", sex: "男")
//克隆對(duì)象
let copyUser:UserCopyModel = user.clone() as! UserCopyModel
//修改克隆對(duì)象的值,看看原型對(duì)象會(huì)不會(huì)改變
copyUser.name = "Andy"
copyUser.sex = "man"
print("原型對(duì)象:name = \(user.name!) sex= \(user.sex!)")
print("克隆對(duì)象:name = \(copyUser.name!) sex= \(copyUser.sex!)")
//打印結(jié)果如下
原型對(duì)象:name = YSL sex= 男
克隆對(duì)象:name = Andy sex= man
- 上面的實(shí)例拷貝的是值類型(直接拷貝數(shù)據(jù)),并不是引用類型,所以不會(huì)改變?cè)蛯?duì)象值
再來看一下原型設(shè)計(jì):數(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ù)組的淺拷貝測(cè)試
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("原型對(duì)象:name = \(student.name!) teachers = \(String(describing: student.teachers![0].name))")
print("克隆對(duì)象:name = \(copyStudent.name!) teachers = \(String(describing: copyStudent.teachers![0].name))")
//輸出結(jié)果
原型對(duì)象:name = Mimi teachers = Optional("Lisa")
克隆對(duì)象:name = DaChanglian teachers = Optional("Lisa")
- 看到以上結(jié)果,應(yīng)該明白,數(shù)組是重新創(chuàng)建了,但是數(shù)組中保存的對(duì)象沒有重新創(chuàng)建(也就是說數(shù)組保存的是對(duì)象的引用類型,那么拷貝的時(shí)候拷貝的是數(shù)組的值,數(shù)組的值就是TeacherModel對(duì)象的引用)。
- 這樣對(duì)數(shù)組中的對(duì)象重新賦值,其實(shí)是改變了對(duì)象的值。如何證明數(shù)組保存的是對(duì)象的引用,直接打印數(shù)組就可以證明了。打印結(jié)果如下:
print("原型對(duì)象:teachers = \(student.teachers!)\n克隆對(duì)象:teachers = \(copyStudent.teachers!)")
原型對(duì)象:teachers = [ArchitectGenerics.TeacherModel, ArchitectGenerics.TeacherModel]
克隆對(duì)象:teachers = [ArchitectGenerics.TeacherModel, ArchitectGenerics.TeacherModel]
如果遇到以上的問題,我們?nèi)绾谓鉀Q這樣的問題呢?答案就是原型模式-->深度拷貝。再看一個(gè)例子,解決一下這個(gè)問題??
//深度拷貝協(xié)議接口
protocol DeepCopyProtocal {
func deepClone() -> AnyObject?
}
//深度拷貝測(cè)試的具體類 老師類
class TeacherModel2: DeepCopyProtocal {
var name:String?
init(name:String) {
self.name = name
}
func deepClone() -> AnyObject? {
return TeacherModel2(name: self.name!)
}
}
//深度拷貝的測(cè)試類 學(xué)生類
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)
}
}
// ============ 深度拷貝測(cè)試===========
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("原型對(duì)象:name = \(student.name!) teachers = \(String(describing: student.teachers![0].name))")
print("克隆對(duì)象:name = \(copyStudent.name!) teachers = \(String(describing: copyStudent.teachers![0].name))")
//=========打印結(jié)果================
原型對(duì)象:name = Mimi teachers = Optional("Jack")
克隆對(duì)象:name = DaChangLian teachers = Optional("Lisa")
- 深度拷貝是重新拷貝對(duì)象(在調(diào)用deepCopy()方法的時(shí)候重新創(chuàng)建了新的對(duì)象),引用對(duì)象的值改變,不影響原型對(duì)象