设计模式 - 备忘录

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

效果:

这个需要配合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

几个关键的地方:

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

时间: 2024-12-13 19:46:02

设计模式 - 备忘录的相关文章

【C#设计模式-备忘录模式】

一.备忘录模式的定义: 在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到原先保存的状态. 二.备忘录模式的结构和角色: 1.Originator(发起人):负责创建一个备忘录Memento,用以记录当前时刻自身的内部状态,并可使用备忘录恢复内部状态.Originator可以根据需要决定Memento存储自己的哪些内部状态. 2.Memento(备忘录):负责存储Originator对象的内部状态,并可以防止Originator以外的其他对象访问

我的设计模式:备忘录模式

我的设计模式-备忘录模式 恢复到最初的状态-->对原始状态的保留和恢复 联想到的业务:cms稿件放入到回收站,永久记录状态得用到数据库啊,怎么办?备忘录模式的内存缓存不适用? 类的单一职责 boy职责:状态   改变状态  设置状态  获取状态 备忘录职责:记录当前的状态   恢复状态 迪 米特原则:最少知道原则,不和陌生人说话 问题:备忘录只是记录了一个节点,多个备忘录记录了多个节点,可以恢复到任意节点?备忘录因该支持多个节点? 思考问题:增加备忘录管理者manager角色,有啥好处呢?没体验

[转] Android中的设计模式-备忘录模式

转自Android中的设计模式-备忘录模式 定义 备忘录设计模式的定义就是把对象的状态记录和管理委托给外界处理,用以维持自己的封闭性. 比较官方的定义 备忘录模式(Memento Pattern)又叫做快照模式(Snapshot Pattern)或Token模式,是GoF的23种设计模式之一,属于行为模式. 定义:在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到原先保存的状态. 角色 笔记本:很多的内部状态需要被建立一个备忘录来管理,创建和取出

设计模式--备忘录模式(Memento)

什么是备忘录模式? 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样就可以将以后的对象状态恢复到先前保存的状态. 我们在编程的时候,经常需要保存对象的中间状态,当需要的时候,可以恢复到这个状态.比如,我们使用Eclipse进行编程时,假如编写失误(例如不小心误删除了几行代码),我们希望返回删除前的状态,便可以使用Ctrl+Z来进行返回.这时我们便可以使用备忘录模式来实现. 代码示例: 代码演示了一个单状态单备份的例子,逻辑非常简单:Originator类中的sta

[工作中的设计模式]备忘录模式memento

一.模式解析 备忘录对象是一个用来存储另外一个对象内部状态的快照的对象.备忘录模式的用意是在不破坏封装的条件下,将一个对象的状态捕捉(Capture)住,并外部化,存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态.备忘录模式常常与命令模式和迭代子模式一同使用. 备忘录模式可以根据客户指令,将相应的对象特有属性进行快照,如果客户要恢复对象,则根据快照提供的特有属性进行还原. 二.模式代码 package memento.patten; /** *备忘录类,同时指定要保存的对象属性

PHP设计模式——备忘录模式

声明:本系列博客參考资料<大话设计模式>,作者程杰. 备忘录模式又叫做快照模式或Token模式,在不破坏封闭的前提下.捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到原先保存的状态. UML类图: 角色: 1.发起人(GameRole):负责创建一个备忘录,用以记录当前时刻自身的内部状态,并可使用备忘录恢复内部状态.发起人能够依据须要决定备忘录存储自己的哪些内部状态. 2.备忘录(RoleStateSaveBox):负责存储发起人对象的内部状态,并能够防止发起人以

设计模式-备忘录模式实现悔棋操作

利用设计模式中的备忘录模式实现多步悔棋的操作 1 import java.util.*; 2 class Chessman { 3 private String label; 4 private int x; 5 private int y; 6 public static int index=-1; 7 public Chessman(String label,int x,int y) { 8 this.label = label; 9 this.x = x; 10 this.y = y; 1

[设计模式] 备忘录模式Memento Pattern

在GOF的<设计模式:可复用面向对象软件的基础>一书中对备忘录模式是这样说的:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到原先保存的状态. 类图和实例: 简单的模式实例: #include <iostream> #include <string> using namespace std; class Memento { private:     string state; public:     Memento(

大话设计模式—备忘录模式

备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象.备忘录模式属于行为型模式.所谓备忘录模式就是在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态.很多时候我们总是需要记录一个对象的内部状态,这样做的目的就是为了允许用户取消不确定或者错误的操作,能够恢复到他原先的状态,使得他有"后悔药"可吃. 大话设计模式中程杰老师给出的定义是,备忘录模式:在不破坏封装性的前提下,捕获一个对象的内