swift设计模式-对象池模式

      对象池模式( object poo patterm) 是单例模式的一 种变体,它可以为组件提供多个完全相同的 对象,而非单个对象。当你需要管理- -组 表示可互相替代的资源的对象,且要求同一时刻 只允许- 个组件使用同一个对象时,便可使用对象池模式。

1.是什么

对象池模式般用来管理组可重用的对象,以供调用组件使用。组件可以从对象池中获取对象,用它来完成任务,用完之后将对象还给对象池,以满足组件未来的使用需求。-个对象在被分配给某个调用组件之后,其他组件在它返回对象池以前都无法使用它

2.有什么优点

对象池模式将对象的构建过程隐藏,使组件无需了解此过程。同时,对象池模式通过重用机制将对象初始化的高昂成本摊销

3.何时使用

不管是因为需要 使用对象来表示现实世界中的资源,还是因为对象的初始化成本高昂,而需要创建一组完全相同的对象,我们都可以使用对象池模式

4.何时应避免

若需要保证任意时刻只存在 一个对象,则不应使用此模式,而应该使用单例模式。如果对存在的对象使用此模式的数量没有限制,并允许调用组件自行创建实例,也不应该使用此模式,而应该使用本书讲解的其他模式,比如工厂方法模式

5.如何确定是

若能在不创建新实例的情况 下给调用组件分配对象,并且相关对象返回到对象池后可以满足组件的后 否正确实现续请求, 就说明正确地实现了对象池模式了此模式

protocol PoolItem {
    var canReuse:Bool {get}
}
class Pool<T> {
    private var data = [T]()
    private var arrayQ = DispatchQueue(label: "arrayQ")
    private let semaphore : DispatchSemaphore
    private var itemCount:Int = 0
    private let maxItemCount :Int
    private let itemFactory:() -> T
    
    private var ejectedItems = 0
    private var poolExhausted = false
    
    init(maxItemCount:Int,factory:@escaping () -> T) {
        self.maxItemCount = maxItemCount
        self.itemFactory = factory
        self.semaphore = DispatchSemaphore(value: maxItemCount)
    }
    
    func getFromPool(maxWaitSecond:Int) -> T? {
        var  result :T?
        let timeOut = DispatchTime.now() + .seconds(maxWaitSecond)
        if !poolExhausted{
            if semaphore.wait(timeout: timeOut) == .success{
                if !poolExhausted{
                    arrayQ.sync {//同步,执行完block,才执行result
                        if self.data.count == 0 && self.itemCount < maxItemCount{
                            result = self.itemFactory()
                            self.itemCount += 1
                            
                        }else{
                            result = self.data.removeFirst()
                        }
                    }
                }
            }
        }
        
        return result
    }
    
    func returnToPool(item:T) {
        arrayQ.async {
            if let pitem = item as? PoolItem{
                if pitem.canReuse{
                    self.data.append(item)
                    self.semaphore.signal()
                }else{
                    self.ejectedItems += 1
                    if self.ejectedItems == self.maxItemCount {
                        self.poolExhausted = true
                        self.flushQueue()
                    }
                }
            }else{
                self.data.append(item)
            }
            
        }
        
    }
    //GCD信号量并未提供唤醒所有等待线程的方式,使用以下方式唤醒
    func flushQueue() {
        let dQueue = DispatchQueue(label: "dQueue", attributes: .concurrent)
        var backLogCleared = false
        
        dQueue.async {
            self.semaphore.wait()
            backLogCleared = true
        }
        //cgd信号量让所有等待的线程以先进先出的方式唤醒执行,也就说,在前边等待的请求通过之前,GCD不会让上边这个闭包执行
        //下边这个闭包反复的发出信号量,直到backlogCleared值发生变化,这样就唤醒了所有等待的线程
        dQueue.async {
            while !backLogCleared {
                self.semaphore.signal()
            }
        }
        
    }
    
    func processPoolItems(callback:([T]) -> Void){
        arrayQ.sync(flags: .barrier) {
            callback(self.data)
        }
    }

 

posted @ 2021-01-30 20:32  不停奔跑的蜗牛  阅读(118)  评论(0编辑  收藏  举报