创建型模式-对象池模式

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设计模式》,如果有兴趣可以直接买来看看,不用看我的"歪曲理解"。我只是一个搬运工,记录过程,记录一点浅显的理解🙏。

上一篇下一篇

猜你喜欢

热点阅读