本案例通过使用对象池模式来复用一个UILabel,效果图如下:
一.对象池的作用简单介绍:
1. 提升对象的使用效率。
在使用大量存活率很短,但逻辑基本相似的情况下,反复的创建对象会消费大量的时间。
而这个时间主要开销在给对象开辟内存空间。对象池模式通过复用这些对象来减少对象的创建从而
达到提升性能。
二.角色分析。
1.可用对象引用列表,功能:
回收对象,并将该对象存入本列表中,下一次再创建对象的时候,
先从判断本列表中是否有可用元素,如果有则直接取出,否则创建新的对象。
2.正在使用对象引用列表,功能:
保存正在使用对象引用,创建对象的时候,先判断可用列表是否有可用对象
如果有可用对象直接取出来,并将该对象从可用列表中移除;
如果没有可用对象则创建一个新对象,并将该对象的引用存入正在使用列表;
函数角色及功能分析如下:
1.验证对象的有效性的函数,保证在取对象的时候取出的对象的有效性;
当被验证的对象无效时,如果该对象存在于可用列表中,需要从该列表中
移除并回收内存;
2.回收对象的函数,主要用于回收无效对象所占用的内存;
3.取对象函数,逻辑:
a.先判断可用列表中是否有对象,如果有则取出该对象并进行验证,
如果有效直接返回,否则进行对象回收处理
b.当步骤a失效时,创建新的对象并将该对象引用存入正在使用的列表中同时
返回该对象给使用者
注意:考虑到这个函数的线程安全性,需要将本函数设计为线程安全的
4.回收对象函数,逻辑:
a.将该对象从正在使用列表中移除,同时判断这个是否还有效
如果有效,则进入可用列表,否则直接回收对象
注意:考虑到这个函数的线程安全性,需要将本函数设计为线程安全的
三.代码设计
为了提高对象对象池的使用灵活性,这里将函数功能角色封装为接口,具体的逻辑由子类支实现
接口代码为:
@protocol ObjPoolListener<NSObject>
@required
-(id) create;
-(BOOL) validate:(id) obj; //验证对象的有效性
-(void) recycObj:(id) obj; //回收对象
-(id) getObjFromPool; //获取对象
-(void) putObj2Pool:(id) obj; //将对象放回池中
@end
@interface BaseObjPool : NSObject<ObjPoolListener>
@property(nonatomic,strong) NSMutableArray* inUseList;
@property(nonatomic,strong) NSMutableArray* availableList;
@end
基类.m文件:
#import "BaseObjPool.h"
@implementation BaseObjPool
-(id) init{
if(self = [super init]){
self.inUseList = [NSMutableArray array];
self.availableList = [NSMutableArray array];
}
return self;
}
/*****************************************
*
*实现协议接口
*
****************************************/
-(id) getObjFromPool{
__block id tmpObj;
if(self.availableList.count > 0){
[self.availableList enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL* _Nonnull stop){
tmpObj = obj;
if([self validate:obj]){
[self.availableList removeObject:tmpObj];
[self.inUseList addObject:tmpObj];
*stop = YES;
}else{
[self.availableList removeObject:tmpObj];
[self recycObj:tmpObj];
*stop = true;
}
}];
}else{
tmpObj = [self create];
[self.inUseList addObject:tmpObj];
}
return tmpObj;
}
/**
将对象放回池中:
1.先将对象从正在使用列表中移除
2.判断这个对象是否被外部调用者置为无效状态,如果被置为无效状态,则直接回收;
否则将其添加到可用列表中,以备下次创建对象时进行复用
@param obj 待放回的对象
*/
-(void) putObj2Pool:(id)obj{
[self.inUseList removeObject:obj];
if([self validate:obj]){
[self.availableList addObject:obj];
}else{
[self recycObj:obj];
}
}
//需要子类重写
-(id) create{
return [[NSObject alloc] init];
}
/**
验证对象是否还有效,此处的验证条件默认为,该对象是否为空
通常需要子类进行重写
@param obj 待验证的对象
@return 返回验证结果
*/
-(BOOL)validate:(id)obj{
return obj != nil;
}
/**
回收对象
@param obj 待回收的对象
*/
-(void) recycObj:(id)obj{
obj = nil;
}
/*****************************************
*
*实现协议接口--end
*
****************************************/
@end
测试用的标签池:
#import <UIKit/UIKit.h>
#import "BaseObjPool.h"
@interface ViewPool : BaseObjPool
@property(nonatomic,strong) UILabel* textView;
@end
.m文件:
#import "ViewPool.h"
@implementation ViewPool
-(id) init{
if(self = [super init] ){
}
return self;
}
-(id) create{
self.textView = [[UILabel alloc] init];
self.textView.text = [NSString stringWithFormat:@"%d",arc4random() % 100];
return self.textView;
}
-(BOOL) validate:(id)obj{
//return self.textView != nil;
return obj != nil;
}
-(void) recycObj:(id)obj{
//self.textView = nil;
obj = nil;
}
@end
在VC中的测试代码:
#import "ViewController.h"
#import "ViewPool.h"
@interface ViewController ()
@property(nonatomic,strong)ViewPool* mPool;
@property(nonatomic,assign)NSInteger nProduceCount;
@property(nonatomic,assign)NSInteger nCoustmerCount;
@end
@implementation ViewController
- (void)viewDidLoad {
[superviewDidLoad];
[selfinitView];
self.mPool = [[ViewPoolalloc] init];
self.nProduceCount =2;
self.nCoustmerCount =1;
}
-(void) initView{
UIButton* createObj = [[UIButtonalloc] initWithFrame:CGRectMake(10,40, 80,40)];
[createObj setTitle:@"创建对象"forState:UIControlStateNormal];
createObj.backgroundColor = [UIColorgrayColor];
createObj.tag =21;
[createObj addTarget:selfaction:@selector(onClick:)forControlEvents:UIControlEventTouchUpInside];
[self.viewaddSubview:createObj];
UIButton* recycObj = [[UIButtonalloc] initWithFrame:CGRectMake(100,40, 130,40)];
[recycObj setTitle:@"回收对象到池中"forState:UIControlStateNormal];
recycObj.backgroundColor = [UIColorgrayColor];
recycObj.tag =22;
[recycObj addTarget:selfaction:@selector(onClick:)forControlEvents:UIControlEventTouchUpInside];
[self.viewaddSubview:recycObj];
UIButton* destoryObj = [[UIButtonalloc] initWithFrame:CGRectMake(235,40, 100,40)];
[destoryObj setTitle:@"销毁对象"forState:UIControlStateNormal];
destoryObj.backgroundColor = [UIColorgrayColor];
destoryObj.tag =23;
[destoryObj addTarget:selfaction:@selector(onClick:)forControlEvents:UIControlEventTouchUpInside];
[self.viewaddSubview:destoryObj];
}
-(void) onClick:(UIButton*) button{
switch (button.tag) {
case21:{
[selfproduceObj];
}
break;
case22:{
[selfputObj2Pool];
}
break;
case23:
[selfdestoryObj];
break;
default:
break;
}
}
-(void) produceObj{
UILabel* tmpView = [self.mPoolgetObjFromPool];
tmpView.frame =CGRectMake(50, self.nProduceCount *50, 100,40);
tmpView.backgroundColor = [UIColorgrayColor];
self.nProduceCount +=1;
tmpView.tag =self.nProduceCount;
[self.viewaddSubview:tmpView];
}
-(void) putObj2Pool{
[self.mPoolputObj2Pool:[self.viewviewWithTag:self.nProduceCount]];
[[self.viewviewWithTag:self.nProduceCount]removeFromSuperview];
self.nProduceCount -=1;
}
-(void) destoryObj{
UILabel* tmpLabel = [self.viewviewWithTag:self.nProduceCount];
if(tmpLabel){
[tmpLabel removeFromSuperview];
[self.mPoolrecycObj:tmpLabel];
self.nProduceCount -=1;
}
}
- (void)didReceiveMemoryWarning {
[superdidReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end