IOS设计模式----对象池模式OBJC版

本文介绍了一个UILabel对象池的实现方案,旨在通过复用UILabel对象来提高应用性能。文中详细阐述了对象池的工作原理、角色分工及其线程安全的考虑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本案例通过使用对象池模式来复用一个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






1、 IOS设计模式的六大设计原则之单一职责原则(SRP,Single Responsibility Principle) 定义   就一个类而言,应该仅有一个引起它变化的原因。 定义解读   这是六大原则中最简单的一种,通俗点说,就是不存在多个原因使得一个类发生变化,也就是一个类只负责一种职责的工作。 优点 类的复杂度降低,一个类只负责一个功能,其逻辑要比负责多项功能简单的多; 类的可读性增强,阅读起来轻松; 可维护性强,一个易读、简单的类自然也容易维护; 变更引起的风险降低,变更是必然的,如果单一职责原则遵守的好,当修改一个功能时,可以显著降低对其他功能的影响。 问题提出   假设有一个类C,它负责两个不同的职责:职责P1和P2。当职责P1需求发生改变而需要修改类C时,有可能会导致原本运行正常的职责P2功能发生故障。 解决方案   遵循单一职责原则。分别建立两个类C1、C2,使C1完成职责P1,C2完成职责P2。这样,当修改类C1时,不会使职责P2发生故障风险;同理,当修改C2时,也不会使职责P1发生故障风险。   说到这里,大家会觉得这个原则太简单了。稍有经验的程序员,即使没有听说过单一职责原则,在设计软件时也会自觉的遵守这一重要原则。在实际的项目开发中,谁也不希望因为修改了一个功能导致其他的功能发生故障。而避免出现这一问题的方法便是遵循单一职责原则。虽然单一职责原则如此简单,并且被认为是常识,即便是经验丰富的程序员写出的程序,也会有违背这一原则的代码存在。为什么会出现这种现象呢?因为有职责扩散。实际项目中,因为某种原因,职责P被分化为粒度更细的职责P1和P2。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值