何为享元模式?
通过共享已存在的对象,减少创建对象内存开销的设计模式被称作享元模式
比如图书馆里,假如有十位同学想看同一本书,图书馆并不需要购买十本相同的书,只需要有一本书用于共享,大家轮流看就好了。
何时使用享元模式
- 需要使用很多对象
- 在内存中保存对象会影响性能
- 对象的多数特有状态可以放到外部而轻量化。
- 移除了外在状态后,可以用较少的共享对象替代原来的那组对象。
- 应用程序不依赖于对象标识,因为共享对象不能提供唯一的标识。
iOS中的应用实例
享元模式的最佳实践就是UITableView的复用机制
超出屏幕外的单元格统一被回收放到一个共享池
等待着被复用
举个例子 :
本文代码地址
假如(不要问我假如是谁)有一个图书馆
图书馆里有几本书比较受欢迎的书
很明显书是可以重复利用的资源
当多位同学来借书的时候
图书馆不需要拥有很多本相同的书
多人可以同看一本书
代码实现:
首先是 BookModel
@interface HXBookModel : NSObject
/** 书名 */
@property (nonatomic, strong) NSString *name;
/** 插画 */
@property (nonatomic, strong) NSString *imageName;
@end
然后是图书馆
用一图书工厂来表示
返回学生想要的书
typedef enum {
HXBookType_Zero,
HXBookType_One,
HXBookType_Two,
HXBookType_Three,
HXBookType_Four,
HXBookType_Five,
HXBookType_Total // 计数用
}HXBookType;
@interface HXBookFactory : NSObject
// 缓存池, 存放享元对象
@property (nonatomic, strong) NSMutableDictionary *bookPool;
// 创建花的工厂方法
- (HXBookModel *)bookWithType:(HXBookType)type;
@end
- (HXBookModel *)bookWithType:(HXBookType)type {
// 去享元池里面取
HXBookModel *book = [self.bookPool objectForKey:[NSNumber numberWithInteger:type]];
// 如果没取到就创建并加入享元池
if (!book) {
book = [[HXBookModel alloc] init];
switch (type) {
case HXBookType_Zero:
book.name = @"0";
book.imageName = @"0-0";
break;
case HXBookType_One:
book.name = @"1";
book.imageName = @"0-1";
break;
case HXBookType_Two:
book.name = @"2";
book.imageName = @"0-2";
break;
case HXBookType_Three:
book.name = @"3";
book.imageName = @"0-3";
break;
case HXBookType_Four:
book.name = @"4";
book.imageName = @"0-4";
break;
case HXBookType_Five:
book.name = @"5";
book.imageName = @"0-5";
break;
default:
break;
}
[self.bookPool setObject:book forKey:[NSNumber numberWithInt:type]];
}
return book;
}
然后假设有 N 多位学生来借书
@interface ViewController ()
// 借来的书
@property (nonatomic, strong) NSMutableArray *bookArray;
// 图书工厂实例
@property (nonatomic, strong) HXBookFactory *bookFactory;
@end
@implementation ViewController
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[self lookLook];
}
// 看一看
- (void)lookLook {
for (NSInteger i = 0; i < 1000 * 500; i++) {
/** 享元模式借阅 */
HXBookType type = arc4random_uniform(HXBookType_Total);
HXBookModel *model = [self.bookFactory bookWithType:type];
[self.bookArray addObject:model];
/** 普通方式借阅 */
// HXBookModel *model = [[HXBookModel alloc] init];
// model.name = @"1";
// model.imageName = @"1-1";
// [self.bookArray addObject:model];
}
}
- (NSMutableArray *)bookArray {
if (!_bookArray) {
_bookArray = [[NSMutableArray alloc] init];
}
return _bookArray;
}
- (HXBookFactory *)bookFactory {
if (!_bookFactory) {
_bookFactory = [[HXBookFactory alloc] init];
}
return _bookFactory;
}
在 lookLook
方法中
实现了两种借阅方式
分别是享元模式的借阅方式和普通借阅方式
两种方式的内存消耗差距还是很大的
总结
1、享元模式可以极大地减少系统中对象的数量。但是它可能会引起系统的逻辑更加复杂化。
2、享元模式的核心在于享元工厂,它主要用来确保合理地共享享元对象。
网友评论