美文网首页
备忘录模式(Memento Pattern)

备忘录模式(Memento Pattern)

作者: iOS_学渣 | 来源:发表于2019-11-27 14:21 被阅读0次
备忘录模式:如果需要对象能返回之前的状态就使用备忘录模式。

备忘录模式是行为性模式之一。
备忘录模式包含原发器(Originator),备忘录(Memento),负责人(Caretaker)三个角色。

备忘录模式

原发器是备忘录的发起者,用来生成一条备忘录,备忘录用来存储原发器的状态。
负责人用于存储备忘录。

举个栗子
很多人经常玩游戏,很多游戏都有保存进度这个说法,可能你进了某个图,如果不保存状态,那么死后装备丢失,金币丢失等等这样一些不合理的情况。
所以我们这里模拟一个游戏的栗子

原发器

#import <Foundation/Foundation.h>

@class PlayerMemento;
NS_ASSUME_NONNULL_BEGIN

@interface Player : NSObject

@property (nonatomic ,strong)NSString * name;
@property (nonatomic ,strong)NSString * sex;
@property (nonatomic ,strong)NSString * idnum;
@property (nonatomic ,assign)NSInteger  experiense;
@property (nonatomic ,assign)NSInteger  level;
@property (nonatomic ,assign)NSInteger  gold;
@property (nonatomic ,assign)NSInteger  ingots;
@property (nonatomic ,assign)NSInteger  blod;
@property (nonatomic ,assign)NSInteger  magicPower;

-(PlayerMemento *)createPlayerMemento;

-(void)setPlayerMemento:(PlayerMemento *)menmento;

@end

NS_ASSUME_NONNULL_END

#import "Player.h"
#import "PlayerMemento.h"

@implementation Player

-(PlayerMemento *)createPlayerMemento {
    
    PlayerMemento * menmento = [[PlayerMemento alloc] init];
    menmento.experiense = self.experiense;
    menmento.level = self.level;
    menmento.gold = self.gold;
    menmento.ingots = self.ingots;
    menmento.blod = self.blod;
    menmento.magicPower = self.magicPower;
    return menmento;
}

-(void)setPlayerMemento:(PlayerMemento *)menmento {
    
    self.experiense = menmento.experiense;
    self.level = menmento.level;
    self.gold = menmento.gold;
    self.ingots = menmento.ingots;
    self.blod = menmento.blod;
    self.magicPower = menmento.magicPower;
    
}

- (NSString *)description
{
    NSDictionary * info = @{@"experiense":@(self.experiense),
                            @"level":@(self.level),
                            @"gold":@(self.gold),
                            @"ingots":@(self.ingots),
                            @"blod":@(self.blod),
                            @"magicPower":@(self.magicPower),
                            };
    return [NSString stringWithFormat:@"<%@:%p,%@>",[self class],self,info];
}

@end

备忘录 .m文件不需要处理任何逻辑,这里只做一个临时的存储

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface PlayerMemento : NSObject

@property (nonatomic ,assign)NSInteger  experiense;
@property (nonatomic ,assign)NSInteger  level;
@property (nonatomic ,assign)NSInteger  gold;
@property (nonatomic ,assign)NSInteger  ingots;
@property (nonatomic ,assign)NSInteger  blod;
@property (nonatomic ,assign)NSInteger  magicPower;

@end

NS_ASSUME_NONNULL_END

careTacker 负责人处理存储逻辑,这里用单例模拟数据库存储逻辑。正确逻辑应该采用数据库存储,避免重新进入应用后数据丢失

#import <Foundation/Foundation.h>
@class PlayerMemento;

NS_ASSUME_NONNULL_BEGIN

@interface PlayerCareTacker : NSObject

+(instancetype)getInstance;

-(void)savePlayerWithIdNum:(NSString *)idNum playerMemento:(PlayerMemento *)memento;

-(PlayerMemento *)getPlayerWithIdNum:(NSString *)idNum;

@end

NS_ASSUME_NONNULL_END

结果演示

#import "ViewController.h"
#import "Player.h"
#import "PlayerMemento.h"
#import "PlayerCareTacker.h"

@interface ViewController ()

@property (nonatomic ,strong)Player * player;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    Player * player = [[Player alloc] init];
    player.name = @"小卤蛋来玩耍";
    player.sex = @"女";
    player.idnum = @"000001";
    player.experiense = 12000;
    player.level = 11;
    player.gold = 3000000;
    player.ingots = 12000;
    player.blod = 14000;
    player.magicPower = 500;
    
    NSLog(@"%@",player);
    
    PlayerMemento * memento = [player createPlayerMemento];
    PlayerCareTacker * careTacker = [PlayerCareTacker getInstance];
    [careTacker savePlayerWithIdNum:player.idnum playerMemento:memento];
    
    _player = player;
    
    [self playerAttackBooss:player];
    
    
    
}

-(void)playerAttackBooss:(Player *)player {
    
    NSLog(@"小卤蛋遇到了大boss,一场大战后小卤蛋不幸阵亡");
    
    player.experiense = 12000;
    player.level = 11;
    player.gold = 10000;
    player.ingots = 1000;
    player.blod = 1;
    player.magicPower = 1;
    
    NSLog(@"%@",player);
    
    [self showDeathCover];
    
}

//展示死亡后的画面
-(void)showDeathCover {
    
    UIButton * btn = [UIButton buttonWithType:UIButtonTypeCustom];
    btn.frame = CGRectMake(0, 200, 375, 200);
    btn.backgroundColor = [UIColor redColor];
    [btn setTitle:@"读取存档" forState:0];
    [btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:btn];
}

-(void)btnClick:(UIButton *)btn {
    
    PlayerCareTacker * careTacker = [PlayerCareTacker getInstance];
    PlayerMemento * memento =  [careTacker getPlayerWithIdNum:_player.idnum];
    [_player setPlayerMemento:memento];
    NSLog(@"%@",_player);
    
}

@end

运行后终端显示运行结果

运行结果

优点

1.将被存储的状态放在外面,不和关键的对象混在一起便于维护内聚
2.保持关键对象的数据封装
3.提供了容易实现的恢复能力

缺点

1.存/取状态的过程可能会非常耗时

相关文章

网友评论

      本文标题:备忘录模式(Memento Pattern)

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