iOS 享元模式

作者: 王技术 | 来源:发表于2019-04-07 20:11 被阅读11次

    何为享元模式?

    通过共享已存在的对象,减少创建对象内存开销的设计模式被称作享元模式
    比如图书馆里,假如有十位同学想看同一本书,图书馆并不需要购买十本相同的书,只需要有一本书用于共享,大家轮流看就好了。

    何时使用享元模式

    • 需要使用很多对象
    • 在内存中保存对象会影响性能
    • 对象的多数特有状态可以放到外部而轻量化。
    • 移除了外在状态后,可以用较少的共享对象替代原来的那组对象。
    • 应用程序不依赖于对象标识,因为共享对象不能提供唯一的标识。
    UML

    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、享元模式的核心在于享元工厂,它主要用来确保合理地共享享元对象。


    工厂模式
    建造者模式
    中介者模式

    相关文章

      网友评论

        本文标题:iOS 享元模式

        本文链接:https://www.haomeiwen.com/subject/qvktiqtx.html