美文网首页
读《Design-Patterns-by-Tutorials》笔

读《Design-Patterns-by-Tutorials》笔

作者: Beyond_JG | 来源:发表于2018-10-03 11:35 被阅读14次

备忘录模式允许一个对象可以被保存和恢复。包括三个部分。

  1. Originator: 需要被保存和恢复的对象。
  2. Memento: 代表保存的状态。
  3. ** Caretaker**: 从 originator 请求保存,并且接收一个 memento 作为响应。caretaker 负责保管这些 memento,并在稍后向 originator 提供这些 memento来恢复 originator 的状态。
    虽然不是严格要求,iOS通常使用Encoder来讲 originator 的状态保存到 memento,并且使用Decoder把 memento 恢复到 originator。这使编码和解码的逻辑可以通用。比如:JSONEncoderJSONDecoder允许一个对象可以编码为 JSON 数据,也可以从JSON数据中解码。
    UML 图如下:
    备忘录模式

When should you use it?

当我们想要保存并且以后需要恢复一个对象的状态时需要用到备忘录模式。
比如:我们可以使用这个模式来实现一个游戏系统,originator 就是游戏的状态(比如:等级,健康状态,生命值等等),memento 就是保存的数据,caretaker 就是游戏系统。
我们可以持续保存一系列数据,表示一个以前的存档。我们也可以用这个模式在 IDEs或者图表软件中实现一些 undo/redo 的特性。

Playground example

备忘录模式表现模式得一种。这是因为这个模式是和保存和恢复表现相关的模式。我们在这个例子中创建一个简单的游戏系统。
首先我们需要定义一个 originator,用以下代码来创建:

import Foundation

// MARK: - Originator
public class Game: Codable {
  
  public class State: Codable {
    public var attemptsRemaining: Int = 3
    public var level: Int = 1
    public var score: Int = 0
  }
  public var state = State()
  
  public func rackUpMassivePoints() {
    state.score += 9002
  }
  
  public func monstersEatPlayer() {
    state.attemptsRemaining -= 1
  }
}

这里,你定义了一个Game类,它有一个内部State保存 game 属性,并且它有操作游戏内动作的方法。我们还要声明GameState遵守Codable协议。
什么是Codable? Apple 在 Swift 4中引进了Codable。任何类型都可以遵守Codable,用 Apple 的话来说就是:转换本身的外部代表。本质上,就是一个可以存储和恢复其自己的类型。听起来很类似?是的,这的确就是我们想让 originator 拥有的能力。
因为GameState的所有属性都遵守了Codable协议,编译器会自动生成Codable协议所必须实现的方法。String,Int,Double和大多数Swift提供的类型都遵守了Codable协议。
Codable是一个typealias,结合了EncodableDecodable协议:

typealias Codable = Decodable & Encodable

可编码类型可以通过Encoder编码为外部表示。外部表示的实际类型取决于你所使用的EncoderFoundation提供了几种默认的编码器,比如J SONEncoder是为了把对象转化为 JSON 数据。
可以通过Decoder把外部表现转化为可解码类型。Foundation也提供了解码器。比如JSONDecoder可以把 JSON 数据转化为对象。
接下来我们需要一个memento,在上面的代码下面添加如下代码:

// MARK: - Memento
typealias GameMemento = Data

理论上,我们一点也不需要这样声明。这里就是说明你GameMemento实际上是Data。这将是Encoder存储的数据,并且是Decoder恢复的元数据。
接下来,我们需要添加一个caretaker,添加如下代码:

// MARK: - CareTaker
public class GameSystem {
  
  private let decoder = JSONDecoder()
  private let encoder = JSONEncoder()
  private let userDefaults = UserDefaults.standard
  
  public func save(_ game: Game, title: String) throws {
    let data = try encoder.encode(game)
    userDefaults.set(data, forKey: title)
  }
  
  public func load(title: String) throws -> Game {
    guard let data = userDefaults.data(forKey: title),
      let game = try? decoder.decode(Game.self, from: data)
      else {
        throw Error.gameNotFound
    }
    return game
  }
  
  public enum Error: String, Swift.Error {
    case gameNotFound
  }
}

我们先来模拟一下游戏过程:

// MARK: - Example
var game = Game()
game.monstersEatPlayer()
game.rackUpMassivePoints()

然后存储一下:

// Save Game
let gameSystem = GameSystem()
try gameSystem.save(game, title: "Best Game Ever")

然后读取一下记录:

// Load Game
game = try! gameSystem.load(title: "Best Game Ever")
print("Loaded Game Score: \(game.state.score)")

Emmm,是不是很不错!

What should you be careful about?

当添加和移除Codable属性时需要当心,编码和解码都是可以抛出错误的。如果我们使用try!强制解包,并且丢失了必要的数据,app 会 crash。
为了规避这种问题,除非你确定操作可以成功,应该尽量避免使用try!。当改变模型时也需要提前规划。比如:我们可以给模型添加版本号或者使用带版本号的数据库。然而我们需要考虑入魂儿处理版本升级。我们可以选择当我们有一个新的版本时删掉旧的数据,或者创建一个升级路径把旧的数据转化为新的数据,或者使用这两种方法的结合。

Tutorial project

下面我们继续给我们以前的 app 增加功能。我们将使用备忘录模式添加一个 app 重要的特性:保存QuestionGroup分数的能力。
实现效果:

备忘录示例

再次运行会在控制台打印:

Hiragana: correctCount 5, incorrectCount 6
Katakana: correctCount 5, incorrectCount 5
Basic Phrases: correctCount 0, incorrectCount 0
Numbers: correctCount 0, incorrectCount 0

Demo

预告

下节我们将学习观察者模式。

相关文章

  • 读《Design-Patterns-by-Tutorials》笔

    单例模式限制一个类仅仅有一个实例。每个这个类的引用都指向同一个实例。在 iOS 开发中非常常见这种模式,因为 Ap...

  • 读《Design-Patterns-by-Tutorials》笔

    备忘录模式允许一个对象可以被保存和恢复。包括三个部分。 Originator: 需要被保存和恢复的对象。 Meme...

  • 读《Design-Patterns-by-Tutorials》笔

    观察者模式让一个对象观察另一个对象的改变。在本章节,你将学习两种实现观察者模式的方法: 使用 KVO 使用一个Ob...

  • 读《Design-Patterns-by-Tutorials》笔

    构造器模式允许一步一步的创建一个复杂的对象而不是一次创建完成。这个模式包括三个主要类型,UML 图如下: Dire...

  • 笔读

    笔读是什么? 笔读就是在读书时,在书上画记号,写记号,写感想,书评文章等方式。 为什么要做笔读呢? 做笔读可以帮自...

  • 关于英语学习和点读笔的使用

    对于口语不好的父母,可以选择点读笔搭配使用。但是不是用了点读笔,父母就把孩子完完全全的交给点读笔了。哪怕用了点读笔...

  • 说下市场上利用率比较高的几款开放式点读笔,可以点读普通书的点读笔

    为什么要说点读笔的利用率比较高呢?因为市场上分2种点读笔类型,一种为封闭式点读笔,一种为开放式点读笔。 封闭式的笔...

  • 点读笔的乐趣

    昨晚和儿子一起玩了会儿点读笔,说起我家这根点读笔,真有种买完笔配不起书的赶脚。 关键是和毛毛虫点读笔配套的点读...

  • 爱贝亲子点读笔产品分析

    爱贝亲子点读笔是一款开放式点读笔,爱贝亲子点读笔凭借着点读笔、点读卡、客户端和网络平台的四维运营模式,让所有的普通...

  • 读笔

    刚开始读《余光中散文精选》时,感觉很无聊,尤其是有些字生僻难懂,都不会读且不认识。第一节的时候有点读不进去,但是当...

网友评论

      本文标题:读《Design-Patterns-by-Tutorials》笔

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