zoukankan      html  css  js  c++  java
  • 设计模式

    设计模式 - 备忘录

    备忘录模式很简单,就是存储对象,然后支持恢复对象到之前的某个状态,玩过游戏的,一定懂得存档一说,备忘录就是对对象的存档与管理。

    效果:

    这个需要配合FastCoder使用,请自行到Github上去搜索源码FastCoder源码^_^!

    源码:

    Model.h 与 Model.m

    //
    //  Model.h
    //  MementoPattern
    //
    //  Created by YouXianMing on 15/1/3.
    //  Copyright (c) 2015年 YouXianMing. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    
    @interface Model : NSObject
    
    @property (nonatomic, strong) NSString *name;
    @property (nonatomic, strong) NSString *age;
    
    /**
     *  初始化方法
     *
     *  @param key 用来标示对象唯一性
     *
     *  @return 对象
     */
    - (instancetype)initWithKey:(NSString *)key;
    
    /**
     *  从某个状态恢复
     *
     *  @param slot 状态槽位(第几个存档位置)
     *  @param key  标示字符串(保证存档唯一)
     *
     *  @return 存档的对象,如果对象不存在,则重新创建
     */
    + (id)recoverFromSlot:(NSInteger)slot key:(NSString *)key;
    
    /**
     *  存储到slot当中(按照数组的顺序)
     */
    - (void)store;
    
    @end
    //
    //  Model.m
    //  MementoPattern
    //
    //  Created by YouXianMing on 15/1/3.
    //  Copyright (c) 2015年 YouXianMing. All rights reserved.
    //
    
    #import "Model.h"
    #import "FastCoder.h"
    #import "NSString+File.h"
    
    @interface Model ()
    
    @property (nonatomic, strong) NSString        *key;
    @property (nonatomic, strong) NSMutableArray  *slotInfoArray;
    
    @end
    
    @implementation Model
    
    - (instancetype)init
    {
        self = [super init];
        if (self) {
            self.key = @"Default";
        }
        return self;
    }
    
    - (instancetype)initWithKey:(NSString *)key {
        Model *model = [Model new];
        model.key    = key;
        
        return model;
    }
    
    + (id)recoverFromSlot:(NSInteger)slot key:(NSString *)key {
        
        if (key == nil) {
            key = @"Default";
        }
        
        NSString *arrayPath  =  [[@"/Documents" path] stringByAppendingString:[NSString stringWithFormat:@"/%@_array", key]];
        NSString *objectPath =  [[@"/Documents" path] stringByAppendingString:[NSString stringWithFormat:@"/%@_%ld", key, (long)slot]];
        
        id object = nil;
        
        NSArray *array = [FastCoder objectWithData:[self dataWithPath:arrayPath]];
        if (array.count > slot && slot >= 0) {
            object = [FastCoder objectWithData:[self dataWithPath:objectPath]];
        }
        
        return object;
    }
    
    - (void)store {
        if (self == nil) {
            return;
        }
        
        self.slotInfoArray = [FastCoder objectWithData:[self dataWithPath:[self arrayPath]]];
        if (self.slotInfoArray.count == 0) {
            [[FastCoder dataWithRootObject:self] writeToFile:[self filePathAtSlot:0]
                                                  atomically:YES];
            
            self.slotInfoArray = [NSMutableArray array];
            [self.slotInfoArray addObject:@""];
            [[FastCoder dataWithRootObject:self.slotInfoArray] writeToFile:[self arrayPath]
                                                                atomically:YES];
        } else {
            [[FastCoder dataWithRootObject:self] writeToFile:[self filePathAtSlot:self.slotInfoArray.count]
                                                  atomically:YES];
            
            [self.slotInfoArray addObject:@""];
            [[FastCoder dataWithRootObject:self.slotInfoArray] writeToFile:[self arrayPath]
                                                                atomically:YES];
        }
        
        NSLog(@"store sucess!");
    }
    
    #pragma mark - private method
    - (NSString *)filePathAtSlot:(NSInteger)slot {
        NSString *path =  [[@"/Documents" path] stringByAppendingString:[NSString stringWithFormat:@"/%@_%ld", self.key, (long)slot]];
        
        return path;
    }
    - (NSString *)arrayPath {
        NSString *path =  [[@"/Documents" path] stringByAppendingString:[NSString stringWithFormat:@"/%@_array", self.key]];
        
        return path;
    }
    - (NSData *)dataWithPath:(NSString *)path {
        return [NSData dataWithContentsOfFile:path];
    }
    + (NSData *)dataWithPath:(NSString *)path {
        return [NSData dataWithContentsOfFile:path];
    }
    
    @end

    NSString+File.h 与 NSString+File.m

    //
    //  NSString+File.h
    //  Category
    //
    //  Created by YouXianMing on 14-8-29.
    //  Copyright (c) 2014年 YouXianMing. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    
    @interface NSString (File)
    
    // 沙盒路径
    - (NSString *)path;
    /*
     /Documents
     /Library/Caches
     /Library/Preferences
     /tmp
     */
    
    // bundle文件
    - (NSString *)bundleFile;
    
    // 检测文件或者文件夹是否存在
    - (BOOL)exist;
    
    // 创建文件夹
    - (BOOL)createFolder;
    
    // 是否是文件夹
    - (BOOL)isDirectory;
    
    // 复制到这个路径
    - (BOOL)copyTo:(NSString *)path;
    
    // 移动到这个路径
    - (BOOL)moveTo:(NSString *)path;
    
    // 删除文件
    - (BOOL)remove;
    
    // 遍历出文件夹中的文件
    - (NSArray *)enumeratorFolder;
    
    // 遍历出文件夹并在block中查看
    - (void)enumeratorFolderEach:(void (^)(NSString *path))block;
    
    // 文件信息
    - (NSDictionary *)fileInfo;
    
    // 文件大小
    - (int)fileSize;
    
    @end
    //
    //  NSString+File.m
    //  Category
    //
    //  Created by YouXianMing on 14-8-29.
    //  Copyright (c) 2014年 YouXianMing. All rights reserved.
    //
    
    #import "NSString+File.h"
    
    @implementation NSString (File)
    
    - (NSString *)path
    {
        return [NSHomeDirectory() stringByAppendingPathComponent:self];
    }
    
    - (NSString *)bundleFile
    {
        return [[NSBundle mainBundle] pathForResource:self
                                               ofType:nil];
    }
    
    - (BOOL)exist
    {
        return [[NSFileManager defaultManager] fileExistsAtPath:[NSHomeDirectory() stringByAppendingPathComponent:self]
                                                    isDirectory:NO];
    }
    
    - (BOOL)createFolder
    {
        return [[NSFileManager defaultManager] createDirectoryAtPath:[NSHomeDirectory() stringByAppendingPathComponent:self]
                                         withIntermediateDirectories:YES
                                                          attributes:nil
                                                               error:nil];
    }
    
    - (BOOL)isDirectory
    {
        BOOL isDirectory = NO;
        
        [[NSFileManager defaultManager] fileExistsAtPath:[NSHomeDirectory() stringByAppendingPathComponent:self]
                                             isDirectory:&isDirectory];
        
        return isDirectory;
    }
    
    - (BOOL)copyTo:(NSString *)path
    {
        return [[NSFileManager defaultManager] copyItemAtPath:[NSHomeDirectory() stringByAppendingPathComponent:self]
                                                       toPath:[NSHomeDirectory() stringByAppendingPathComponent:path]
                                                        error:nil];
    }
    
    - (BOOL)moveTo:(NSString *)path
    {
        return [[NSFileManager defaultManager] moveItemAtPath:[NSHomeDirectory() stringByAppendingPathComponent:self]
                                                       toPath:[NSHomeDirectory() stringByAppendingPathComponent:path]
                                                        error:nil];
    }
    
    - (BOOL)remove
    {
        return [[NSFileManager defaultManager] removeItemAtPath:[NSHomeDirectory() stringByAppendingPathComponent:self]
                                                          error:nil];
    }
    
    - (NSArray *)enumeratorFolder
    {
        if ([self isDirectory])
        {
            NSMutableArray *storeArray = [NSMutableArray array];
            
            NSString *docsDir = [NSHomeDirectory() stringByAppendingPathComponent:self];
            NSFileManager *localFileManager = [[NSFileManager alloc] init];
            NSDirectoryEnumerator *dirEnum = [localFileManager enumeratorAtPath:docsDir];
            
            NSString *file;
            while ((file = [dirEnum nextObject]))
            {
                [storeArray addObject:[[NSHomeDirectory() stringByAppendingPathComponent:self] stringByAppendingPathComponent:file]];
            }
            
            return storeArray;
        }
        else
        {
            return nil;
        }
    }
    
    - (void)enumeratorFolderEach:(void (^)(NSString *path))block
    {
        if ([self isDirectory])
        {
            NSMutableArray *storeArray = [NSMutableArray array];
            
            NSString *docsDir = [NSHomeDirectory() stringByAppendingPathComponent:self];
            NSFileManager *localFileManager = [[NSFileManager alloc] init];
            NSDirectoryEnumerator *dirEnum = [localFileManager enumeratorAtPath:docsDir];
            
            NSString *file;
            while ((file = [dirEnum nextObject]))
            {
                [storeArray addObject:[self stringByAppendingPathComponent:file]];
            }
            
            [storeArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
                block(obj);
            }];
        }
    }
    
    - (NSDictionary *)fileInfo
    {
        return [[NSFileManager defaultManager] attributesOfItemAtPath:[NSHomeDirectory() stringByAppendingPathComponent:self]
                                                                error:nil];
    }
    
    - (int)fileSize
    {
        return [[[[NSFileManager defaultManager] attributesOfItemAtPath:[NSHomeDirectory() stringByAppendingPathComponent:self]
                                                                  error:nil] 
                 objectForKey:@"NSFileSize"] intValue];
    }
    
    @end

    控制器源码:

    //
    //  ViewController.m
    //  MementoPattern
    //
    //  Created by YouXianMing on 15/1/3.
    //  Copyright (c) 2015年 YouXianMing. All rights reserved.
    //
    
    #import "ViewController.h"
    #import "NSString+File.h"
    #import "Model.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        Model *model_01 = [Model new];
        model_01.name   = @"YouXianMing";
        model_01.age    = @"27";
        [model_01 store]; // 存快照
        
        Model *model_02 = [Model new];
        model_02.name   = @"QiuLiang";
        model_02.age    = @"28";
        [model_02 store]; // 存快照
        
        Model *model_03 = [Model new];
        model_03.name   = @"XiaoMing";
        model_03.age    = @"100";
        [model_03 store]; // 存快照
    
    //    Model *test_model_01 = [Model recoverFromSlot:0 key:nil];
    //    NSLog(@"%@ %@", test_model_01.name, test_model_01.age);
    //    
    //    Model *test_model_02 = [Model recoverFromSlot:1 key:nil];
    //    NSLog(@"%@ %@", test_model_02.name, test_model_02.age);
    //    
    //    Model *test_model_03 = [Model recoverFromSlot:2 key:nil];
    //    NSLog(@"%@ %@", test_model_03.name, test_model_03.age);
    }
    
    
    
    @end

    几个关键的地方:

    原理其实非常简单,就是将对象写文件,然后从文件从恢复出对象,但一定要有管理的功能,本例中并没有处理如何删除存档,其实存档可以做成堆栈或者队列模式,这个因需求而已,本处本人只是抛砖引玉,简单介绍下备忘录设计模式!

  • 相关阅读:
    JavaScript 倒计时器,闹钟功能
    JS实现手风琴效果
    JS原生选项卡 – 幻灯片效果
    JS/CSS 响应式样式实例
    JS/CSS 全屏幕导航 – 从上到下动画
    JS实现下拉菜单的功能
    node.js服务器核心http和文件读写
    JS实现联想自动补齐功能
    JS搜索菜单实现
    关于写专利(专利交底书)
  • 原文地址:https://www.cnblogs.com/YouXianMing/p/4200045.html
Copyright © 2011-2022 走看看