使用場景:只需要一個實例肺然。例如現(xiàn)實世界的資源:服務(wù)器蔫缸;或封裝共享資源腿准。
意義:
1际起、使得創(chuàng)建的實例始終保持一份,避免多次創(chuàng)建吐葱。
2街望、對象與現(xiàn)實資源對應(yīng)。
3弟跑、封裝共享資源灾前。
創(chuàng)建Swift單例
1、使用全局常量
//全局變量
let globalLogger = Logger()
//final修飾后孟辑,防止子類創(chuàng)建
final class Logger{
private var data = [String]()
private let arrayQ = DispatchQueue.init(label: "arrayQ")
//只在本文件有效,防止其他地方實例
fileprivate init() {
}
func log(msg:String){
//同步添加數(shù)組
arrayQ.sync {
data.append(msg)
}
}
func printLog(){
for msg in data {
print("Log:\(msg)")
}
}
}
2哎甲、使用結(jié)構(gòu)體
final class BackupServer {
//防止外界初始化
fileprivate init(name:String) {
self.name = name
globalLogger.log(msg: "Created new server \(name)")
}
//BackupServer類型的屬性server,初始化值是結(jié)構(gòu)體的靜態(tài)屬性
class var server:BackupServer{
//結(jié)構(gòu)體
struct SingletonWrapper{
//靜態(tài)屬性饲嗽,用實例賦值
static let singleton = BackupServer.init(name: "MainServer")
}
//返回結(jié)構(gòu)體的屬性值
return SingletonWrapper.singleton
}
}
使用注意:
1炭玫、Swift的單例模式只適用于引用類型,即類貌虾。結(jié)構(gòu)體和其他值類型是不能用的吞加,因為結(jié)構(gòu)體本身具有復(fù)制功能。
2尽狠、處理并發(fā)衔憨。因為單例是共享資源,里面如果有數(shù)組袄膏、字典等集合践图,在讀寫操作的時候就需要考慮線程安全問題,避免出現(xiàn)多個線程同時寫一個集合沉馆。Swift3的GCD需要適應(yīng)一下码党。
- 使用串行赫舒,如上使用全局變量創(chuàng)建單例中,使用到的
func log(msg:String){
//同步添加數(shù)組
arrayQ.sync {
data.append(msg)
}
}
- 也可以串行寫闽瓢,并行讀接癌。用到了
barrier
,它的功能就是扣讼,barrier block
到達(dá)隊列頂端時缺猛,變成串行隊列,所有操作都要等待它完成椭符,完成后恢復(fù)并行隊列荔燎,直到出現(xiàn)下一個barrier block
。
var arrayQ = DispatchQueue.init(label: "arrayQ")
func logItem(item:T) {
//dispatch_barrier 最新寫法
//當(dāng)barrier隊列執(zhí)行的時候销钝,其他線程不能執(zhí)行有咨,就是串行隊列
//執(zhí)行到其他隊列的時候就是并行隊列,直到運(yùn)行到下一個barrier
arrayQ.async(execute: DispatchWorkItem.init(qos: DispatchQoS.default, flags: DispatchWorkItemFlags.barrier, block: {
self.dataItems.append(item.copy() as! T)
self.callback(item)
}))
}
demo
寫在后面:
我寫的關(guān)于設(shè)計模式內(nèi)容蒸健,都是來自書《精通Swift設(shè)計模式》
座享,如果有興趣可以直接買來看看,不用看我的"歪曲理解"似忧。我只是一個搬運(yùn)工渣叛,記錄過程,記錄一點淺顯的理解??盯捌。