Skip to content

Instantly share code, notes, and snippets.

@norio-nomura
Created November 7, 2017 12:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save norio-nomura/65db97c4786851bc368a8d68834fb31b to your computer and use it in GitHub Desktop.
Save norio-nomura/65db97c4786851bc368a8d68834fb31b to your computer and use it in GitHub Desktop.
class Mario {
enum State: RawState {
case normal = "normal"
case big = "big"
case fire = "fire"
case dead = "dead"
}
var state: State = .normal
var name: String { return "\(state.rawValue.name)マリオ" }
func hitEnemy() { state.rawValue.hitEnemy(self) }
}
private protocol MarioStateBehavior {
var name: String { get }
func hitEnemy(_ mario: Mario)
}
protocol Factory {
init(factory: Self)
}
extension Factory {
init(factory: Self) {
self = factory
}
}
class RawState: MarioStateBehavior, RawRepresentable, Equatable, ExpressibleByStringLiteral, Factory {
// MarioStateBehavior
var name: String { fatalError("unreachable") }
func hitEnemy(_ mario: Mario) { fatalError("unreachable") }
// RawRepresentable
var rawValue: String
required init(rawValue: String) { self.rawValue = rawValue }
// Equatable
static func == (lhs: RawState, rhs: RawState) -> Bool { return lhs.rawValue == rhs.rawValue }
// ExpressibleByStringLiteral
required convenience init(stringLiteral value: String) {
switch value {
case "normal": self.init(factory: Normal(rawValue: value))
case "big": self.init(factory: Big(rawValue: value))
case "fire": self.init(factory: Fire(rawValue: value))
case "dead": self.init(factory: Dead(rawValue: value))
default: fatalError("unreachable")
}
}
}
class Normal: RawState {
override var name: String { return "チビ" }
override func hitEnemy(_ mario: Mario) {
print("死ぬ")
mario.state = .dead
}
}
class Big: RawState {
override var name: String { return "スーパー" }
override func hitEnemy(_ mario: Mario) {
print("チビマリオになる")
mario.state = .normal
}
}
class Fire: RawState {
override var name: String { return "ファイアー" }
override func hitEnemy(_ mario: Mario) {
print("チビマリオになる")
mario.state = .normal
}
}
class Dead: RawState {
override var name: String { return "死んだ" }
override func hitEnemy(_ mario: Mario) {
print("死ぬ")
}
}
// 以下使用例
let mario = Mario()
mario.name //=> "チビマリオ"
mario.hitEnemy() //=> print 死ぬ
mario.state // dead
mario.state = .big
mario.name //=> "スーパーマリオ"
mario.hitEnemy() //=> print チビマリオになる
mario.state // normal
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment