创建型模式-对象池模式
2017-03-20 本文已影响207人
关灯侠
使用场景:需要创建一组完全一样的对象,且数量一定
意义:
1、可以表示现实生活中的资源,例如某类图书的借与还。
2、对存在对象数量有限制。
原理描述:
一组固定数量的相同对象(对象池),使用者必须有借有还。
对象池.png具体实现:
1、创建一个对象池类Pool。功能:创建固定数量的抽象对象、存对象、取对象。
import Foundation
//泛型数据
class Pool<T>{
private var data = [T]()
//自定义队列
private let arrayQ = DispatchQueue.init(label: "arrayQ")
// 为什么要引入信号量,在一种极端情况下,数组中只有一个元素,两个线程先后访问,第一个线程正在取元素的同时,第二个线程也在取。当第一个线程取完的时候,第二个线程继续取的时候数组会空就会报错
private let semaphore : DispatchSemaphore
//初始化时,data保存传入的数组
init(items:[T]) {
data.reserveCapacity(data.count)
for itme in items {
data.append(itme)
}
//创建一个和数组个数相等的信号量
semaphore = DispatchSemaphore.init(value: items.count)
}
//从data数组中取出第一个对象,同时删除第一个对象
func getFromPool() -> T? {
var result:T?
//信号量减1,判断是否还有信号
let sempResult = semaphore.wait(timeout: DispatchTime.distantFuture)
if sempResult == DispatchTimeoutResult.success {
//同步删除元素
arrayQ.sync {
result = self.data.remove(at: 0)
}
}
return result
}
//返还对象给data数组
func returnToPool(item:T) {
arrayQ.async {
self.data.append(item)
//信号量加1
self.semaphore.signal()
}
}
}
注意:
a、为什么使用泛型创建,这样做对象池就能适用各种类型的对象存取。
b、使用信号量是避免,异步存取的时候数组为空,Swfit3.0信号量使用有点改变。
c、删除元素的是同步队列,添加元素的是异步队列。
2、创建一个管理对象池的类Library。功能:使用具体的类创建对象池、提供具体的存、取方法。还必须是一个单例,因为它只需要保持一份,内部创建一个保存有固定对象的对象池即可。
import Foundation
final class Library{
private var books:[Book]
private let pool:Pool<Book>
//初始化对象池里面的对象数量
init(stockLevel:Int) {
books = [Book]()
for count in 1 ... stockLevel {
books.append(Book.init(author: "Dickens", title: "Hard times", stock: count))
}
pool = Pool<Book>.init(items: books)
}
//单例,对象池里注入两个book对象
private class var singleton : Library{
struct SinglestonWrapper{
static let singleton = Library.init(stockLevel: 2)
}
return SinglestonWrapper.singleton
}
//借书
class func checkoutBook(reader:String) -> Book?{
let book = singleton.pool.getFromPool()
book?.reader = reader
book?.checkoutCount = (book?.checkoutCount)! + 1
return book
}
//还书
class func returnBook(book:Book){
book.reader = nil
singleton.pool.returnToPool(item: book)
}
class func printReport(){
for book in singleton.books {
print("...Book#\(book.stockNumber)...")
print("Checked out \(book.checkoutCount) times")
if book.reader != nil {
print("Checked out to \(book.reader!)")
}else{
print("In stock")
}
}
}
}
3、使用。取出对象池的对象,改变对象的属性,操作完后,返还给对象池。
import Foundation
print("Hello, World!")
var queue = DispatchQueue.init(label: "workQ")
var group = DispatchGroup()
print("Strating...")
for i in 1 ... 20{
queue.async(group: group, execute: DispatchWorkItem.init(block: {
var book = Library.checkoutBook(reader: "reader#\(i)")
if book != nil{
Thread.sleep(forTimeInterval: (Double(arc4random() % 2)))
Library.returnBook(book: book!)
}
}))
}
_ = group.wait(timeout: .distantFuture)
print("All blocks complete")
Library.printReport()
demo:对象池模式、SportsStoreDemo中的ProdunctDataStore、NetworkPool、NetworkConnection
写在后面:
我写的关于设计模式内容,都是来自书《精通Swift设计模式》
,如果有兴趣可以直接买来看看,不用看我的"歪曲理解"。我只是一个搬运工,记录过程,记录一点浅显的理解🙏。