Method Chain
class Creature : CustomStringConvertible
{
var name : String
var attack : Int
var defense : Int
init(name: String, attack: Int, defense: Int)
{
self.name = name
self.attack = attack
self.defense = defense
}
var description: String
{
return "Name: \(name), Attack = \(attack), Defense = \(defense)"
}
}
class CreatureModifier
{
let creature : Creature
var next : CreatureModifier?
init(creature : Creature)
{
self.creature = creature
}
func add(_ cm: CreatureModifier)
{
if next != nil
{
next!.add(cm)
}
else
{
next = cm
}
}
func handle()
{
next?.handle() // handle
}
}
class DoubleAttackModifier : CreatureModifier
{
override func handle()
{
print("Doubling \(creature.name)'s attack")
creature.attack *= 2
super.handle()
}
}
class IncreaseDefenseModifier : CreatureModifier
{
override func handle()
{
print("Increasing \(creature.name)'s defense")
creature.defense += 3
super.handle()
}
}
// can cancell
class NoBonusesModifier : CreatureModifier
{
override func handle()
{
// nothing
}
}
func main()
{
let Bear = Creature(name: "Bear", attack: 2, defense: 2)
print(Bear)
let root = CreatureModifier(creature: Bear)
// root.add(NoBonusesModifier(creature: Bear))
print("Let's double the bear's attack")
root.add(DoubleAttackModifier(creature: Bear))
print("Let's increase bear's defense")
root.add(IncreaseDefenseModifier(creature: Bear))
root.handle()
print(Bear)
}
Broker Chain
protocol Invocable : class
{
func invoke(_ data: Any)
}
public protocol Disposable
{
func dispose()
}
public class Event<T>
{
public typealias EventHandler = (T) -> ()
var eventHandlers = [Invocable]()
public func raise(_ data: T)
{
for handler in self.eventHandlers
{
handler.invoke(data)
}
}
public func addHandler<U: AnyObject>
(target: U, handler: @escaping (U) -> EventHandler) -> Disposable
{
let subscription = Subscription(target: target, handler: handler, event: self)
eventHandlers.append(subscription)
return subscription
}
}
class Subscription<T: AnyObject, U> : Invocable, Disposable
{
weak var target: T?
let handler: (T) -> (U) -> ()
let event: Event<U>
init(target: T?, handler: @escaping (T) -> (U) -> (), event: Event<U>)
{
self.target = target
self.handler = handler
self.event = event
}
func invoke(_ data: Any) {
if let t = target {
handler(t)(data as! U)
}
}
func dispose()
{
event.eventHandlers = event.eventHandlers.filter { $0 as AnyObject? !== self }
}
}
// CQS
class Query
{
var creatureName : String
enum Argument
{
case attack
case defense
}
var whatToQuery: Argument
var value : Int
init(_ name: String, _ whatToQuery: Argument, _ value: Int)
{
self.creatureName = name
self.whatToQuery = whatToQuery
self.value = value
}
}
class Game
{
let queries = Event<Query>()
func performQuery(_ q: Query)
{
queries.raise(q)
}
}
class Creature: CustomStringConvertible
{
var name: String
private let _attack, _defense: Int
private let game: Game
init(_ game: Game, _ name: String, _ attack: Int, _ defense: Int)
{
self.game = game
self.name = name
_attack = attack
_defense = defense
}
var attack: Int
{
let q = Query(name, .attack, _attack)
game.performQuery(q)
return q.value
}
var defense: Int
{
let q = Query(name, .defense, _defense)
game.performQuery(q)
return q.value
}
var description: String
{
return "Name: \(name), Attack = \(attack), Defense = \(defense)"
}
}
class CreatureModifier : Disposable
{
let game: Game
let creature : Creature
var event: Disposable? = nil
init(_ game: Game, _ creature: Creature)
{
self.game = game
self.creature = creature
event = self.game.queries.addHandler(target: self, handler: CreatureModifier.handle)
}
func handle(_ q: Query)
{
}
func dispose()
{
event?.dispose()
}
}
class DoubleAttackModifier: CreatureModifier
{
override func handle(_ q: Query)
{
if q.creatureName == creature.name && q.whatToQuery == .attack
{
q.value *= 2
}
}
}
class IncreaseDefenseModifier: CreatureModifier
{
override func handle(_ q: Query)
{
if q.creatureName == creature.name && q.whatToQuery == .defense
{
q.value += 2
}
}
}
func main()
{
let game = Game()
let bear = Creature(game, "Bear", 3, 5)
print("Baseline : \(bear)")
let dam = DoubleAttackModifier(game, bear)
print("Bear with double attack : \(bear)")
let idm = IncreaseDefenseModifier(game,bear)
print("Bear with increase defense : \(bear)")
idm.dispose()
print("Bear is now \(bear)")
dam.dispose()
print("Bear is now \(bear)")
}