『ios』设计模式—备忘录模式

2021-08-18  本文已影响0人  butterflyer

这个模式的产生是用来解决一种场景,为了允许用户取消不确定或者错误的操作,能够恢复到他原先的状态,使得他有"后悔药"可吃。
备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象。备忘录模式属于行为型模式。
看到这个场景我们可能想到的是,把用户的状态存下来。那么如何再不破坏封装性的前提下,设计一个备忘中心来统一的调度呢?

那么接下来我们就需要来设计一个MementoCenter备忘中心。

首先我们定义一个协议MementoCenterPotocol,里面包含了两个方法,一个是currentState的方法,一个是recoverFromState状态。

@protocol MementoCenterPotocol <NSObject>

- (id)currentState;

- (void)recoverFromState:(id)state;

@end

再来设计单独的类,MementoCenter,包含saveMementoObject和mementoObjectWithKey的方法,这个类是用来存储和取出备忘状态的类。

@implementation MementoCenter

+ (void)saveMementoObject:(id<MementoCenterPotocol>)object withKey:(NSString *)key {
    NSParameterAssert(object);
    NSParameterAssert(key);
    
    //获取data,通过potocol确定object的那些property需要存储
    id data = [object currentState];
    NSData *tmpData = [FastCoder dataWithRootObject:data];
    
    //存储data
    if (tmpData) {
        [[NSUserDefaults standardUserDefaults] setObject:tmpData forKey:key];
    }
}

+ (id)mementoObjectWithKey:(NSString *)key {
    NSParameterAssert(key);
    
    id data = nil;
    NSData *tmpData = [[NSUserDefaults standardUserDefaults] objectForKey:key];
    
    if (tmpData) {
        data = [FastCoder objectWithData:tmpData];
    }
    return data;
}

@end

然后我们需要给nsobject加一个分类,目的是为了给所有的nsobject对象都添加这个备忘的功能,需要保证
所有的调用的这两个方法的对象都遵循了MementoCenterPotocol的协议。

@implementation NSObject (MementoCenter)

- (void)saveStateWithKey:(NSString *)key {
    NSParameterAssert(key);
    
    id <MementoCenterPotocol> obj = (id <MementoCenterPotocol>)self;
    if ([obj respondsToSelector:@selector(currentState)]) {
        [MementoCenter saveMementoObject:obj withKey:key];
    }
}

- (void)recoverFromStateWithKey:(NSString *)key {
    NSParameterAssert(key);
    
    id <MementoCenterPotocol> obj = (id <MementoCenterPotocol>)self;
    if ([obj respondsToSelector:@selector(recoverFromStateWithKey:)]) {
        id state = [MementoCenter mementoObjectWithKey:key];
        if (state) {
            [obj recoverFromState:state];
        }
    }
}

@end

最后一步就是来使用他了。我们来对一个view进行备忘和恢复操作,设计一个view,并且遵守MementoCenterPotocol

@interface DemoView : UIView <MementoCenterPotocol>

@end
@implementation CustomView

//返回demoView的frame
- (id)currentState {
    return @{@"frame" : NSStringFromCGRect(self.frame)};
}
//恢复CustomView的frame
- (void)recoverFromState:(id)state {
    NSDictionary *data = state;
    [UIView animateWithDuration:3.f animations:^{
        
        self.frame = CGRectFromString(data[@"frame"]);
    }];
}
@end

使用,先存储当前状态,再恢复状态。

- (void)test1 {
    _demoView.frame     = CGRectMake(100, 100, 100, 100);
    [_demoView saveStateWithKey:@"demoView"];
    NSLog(@"%@", _demoView);
}

- (void)test2 {
    //注意log
    NSLog(@"%@", _demoView);
    NSLog(@"*******************");
    [_demoView recoverFromStateWithKey:@"demoView"];
    NSLog(@"%@", _demoView);
}
上一篇下一篇

猜你喜欢

热点阅读