@startuml
package com.iluwatar.command {
  class App {
    + App()
    + main(args : String[]) {static}
  }
  interface Command {
    + Command()
    + execute(Target) {abstract}
    + redo() {abstract}
    + toString() : String {abstract}
    + undo() {abstract}
  }
  class Goblin {
    + Goblin()
    + toString() : String
  }
  class InvisibilitySpell {
    - target : Target
    + InvisibilitySpell()
    + execute(target : Target)
    + redo()
    + toString() : String
    + undo()
  }
  class ShrinkSpell {
    - oldSize : Size
    - target : Target
    + ShrinkSpell()
    + execute(target : Target)
    + redo()
    + toString() : String
    + undo()
  }
  enum Size {
    + NORMAL {static}
    + SMALL {static}
    - title : String
    + toString() : String
    + valueOf(name : String) : Size {static}
    + values() : Size[] {static}
  }
  abstract class Target {
    - LOGGER : Logger {static}
    - size : Size
    - visibility : Visibility
    + Target()
    + getSize() : Size
    + getVisibility() : Visibility
    + printStatus()
    + setSize(size : Size)
    + setVisibility(visibility : Visibility)
    + toString() : String {abstract}
  }
  enum Visibility {
    + INVISIBLE {static}
    + VISIBLE {static}
    - title : String
    + toString() : String
    + valueOf(name : String) : Visibility {static}
    + values() : Visibility[] {static}
  }
  class Wizard {
    - LOGGER : Logger {static}
    - redoStack : Deque<Command>
    - undoStack : Deque<Command>
    + Wizard()
    + castSpell(command : Command, target : Target)
    + redoLastSpell()
    + toString() : String
    + undoLastSpell()
  }
}
Target -->  "-size" Size
Wizard -->  "-undoStack" Command
ShrinkSpell -->  "-oldSize" Size
InvisibilitySpell -->  "-target" Target
ShrinkSpell -->  "-target" Target
Target -->  "-visibility" Visibility
Goblin --|> Target
InvisibilitySpell ..|> Command
ShrinkSpell ..|> Command
@enduml
