diff --git a/README.md b/README.md
index 2586809..e1497e1 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,976 @@
# ruby-patterns
Examples of Patterns in Ruby
-Pd: I'd like recommend you visit my last gem worked: [Ate](https://github.com/TheBlasfem/ate), is a new template engine for Ruby, is minimalist and simple to use, hope you enjoy it!
+## Table of Contents
+
+ 1. [Adapter](#adapter)
+ 1. [Builder](#builder)
+ 1. [Command](#command)
+ 1. [Composite](#composite)
+ 1. [Decorator](#decorator)
+ 1. [Facade](#facade)
+ 1. [Factory](#factory)
+ 1. [Interpreter](#interpreter)
+ 1. [Iterator](#iterator)
+ 1. [Observer](#observer)
+ 1. [Proxy](#proxy)
+ 1. [Singleton](#singleton)
+ 1. [State](#state)
+ 1. [Strategy](#strategy)
+ 1. [Template](#template)
+
+## Adapter
+ - Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.[[link](#adapter)]
+
+ ```ruby
+ class Quest
+ attr_accessor :difficulty, :hero
+
+ def initialize(difficulty)
+ @difficulty = difficulty
+ @hero = nil
+ end
+
+ def finish
+ @hero.exp += calculate_experience
+ end
+
+ def calculate_experience
+ @difficulty * 50 / @hero.level
+ end
+ end
+
+ class Hero
+ attr_accessor :level, :exp, :quests
+
+ def initialize
+ @level = 1
+ @exp = 0
+ @quests = []
+ end
+
+ def take_quest(quest)
+ @quests << (quest.hero = self)
+ end
+
+ def finish_quest(quest)
+ quest.finish
+ @quests.delete quest
+ end
+ end
+
+ class OldQuest
+ attr_accessor :hero, :difficulty, :experience
+
+ def initialize
+ @difficulty = 3
+ @experience = 10
+ end
+
+ def done
+ difficulty * experience
+ end
+ end
+
+ class QuestAdapter
+ attr_accessor :hero
+
+ def initialize(old_quest, difficulty)
+ @old_quest = old_quest
+ @old_quest.difficulty = difficulty
+ @hero = nil
+ end
+
+ def finish
+ @hero.exp += @old_quest.done
+ end
+ end
+
+ # Usage
+ hero = Hero.new
+ quest = Quest.new 5
+ hero.take_quest quest
+ hero.finish_quest quest
+ puts hero.exp
+ # => 250
+ some_old_quest = OldQuest.new
+ old_quest_adapted = QuestAdapter.new(some_old_quest, 5)
+ hero.take_quest old_quest_adapted
+ hero.finish_quest old_quest_adapted
+ puts hero.exp
+ # => 300
+ ```
+
+**[Back to top](#table-of-contents)**
+
+## Builder
+ - Separate the construction of a complex object from its representation so that the same construction process can create different representations.[[link](#builder)]
+
+ ```ruby
+ class BoardBuilder
+ def initialize(width, height)
+ @board = Board.new
+ @board.width = width
+ @board.height = height
+ @board.tiles = []
+ @board.monsters = []
+ end
+
+ def add_tiles(n)
+ n.times{ @board.tiles << Tile.new }
+ end
+
+ def add_monsters(n)
+ n.times{ @board.monsters << Monster.new }
+ end
+
+ def board
+ @board
+ end
+ end
+
+ class Board
+ attr_accessor :width, :height, :tiles, :monsters
+ def initialize
+ end
+ end
+
+ class Tile; end
+ class Monster; end
+
+ # Usage
+ builder = BoardBuilder.new 2, 3
+ puts builder.board
+ # => Board Object
+ board = builder.board
+ puts board.width
+ # => 2
+ builder.add_tiles(3)
+ builder.add_monsters(2)
+ puts board.tiles.size
+ # => 3
+ puts board.monsters.size
+ # => 2
+ ```
+
+**[Back to top](#table-of-contents)**
+
+## Command
+ - Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.[[link](#command)]
+
+ ```ruby
+ class Turn
+ def initialize
+ @commands = []
+ end
+
+ def run_command(command)
+ command.execute
+ @commands << command
+ end
+
+ def undo_command
+ @commands.pop.unexecute
+ end
+ end
+
+ class Hero
+ attr_accessor :money, :health
+
+ def initialize
+ @money = 0
+ @health = 100
+ end
+ end
+
+ class GetMoneyCommand
+ def initialize(hero)
+ @hero = hero
+ end
+
+ def execute
+ @hero.money += 10
+ end
+
+ def unexecute
+ @hero.money -= 10
+ end
+ end
+
+ class HealCommand
+ def initialize(hero)
+ @hero = hero
+ end
+
+ def execute
+ @hero.health += 10
+ end
+
+ def unexecute
+ @hero.health -= 10
+ end
+ end
+
+ # Usage
+ hero = Hero.new
+ get_money = GetMoneyCommand.new hero
+ heal = HealCommand.new hero
+ turn = Turn.new
+ turn.run_command(heal)
+ puts hero.health
+ # => 110
+ turn.run_command(get_money)
+ puts hero.money
+ # => 10
+ turn.undo_command
+ puts hero.money
+ # => 0
+ ```
+
+**[Back to top](#table-of-contents)**
+
+## Composite
+ - Composition over inheritance. Compose objects into tree structures to represent part-whole hierarchies.[[link](#composite)]
+
+ ```ruby
+ class CompositeQuest
+ def initialize
+ @tasks = []
+ end
+
+ def <<(task)
+ @tasks << task
+ end
+
+ def reward
+ @tasks.inject(0){ |sum, task| sum += task.reward }
+ end
+ end
+
+ class MegaQuest < CompositeQuest
+ end
+
+ class Quest < CompositeQuest
+ end
+
+ class MonsterTask
+ attr_reader :reward
+
+ def initialize
+ @reward = 100
+ end
+ end
+
+ class PuzzleTask
+ attr_reader :reward
+
+ def initialize
+ @reward = 200
+ end
+ end
+
+ # Usage
+ quest1 = Quest.new
+ quest1 << MonsterTask.new
+ quest1 << PuzzleTask.new
+ puts quest1.reward
+ # => 300
+
+ quest2 = Quest.new
+ quest2 << MonsterTask.new
+ quest2 << PuzzleTask.new
+ megaquest = MegaQuest.new
+ megaquest << quest1
+ megaquest << quest2
+ puts megaquest.reward
+ # => 600
+ ```
+
+**[Back to top](#table-of-contents)**
+
+## Decorator
+ - Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.[[link](#decorator)]
+
+ ```ruby
+ class ItemDecorator
+ def initialize(item)
+ @item = item
+ end
+ # this needs to be delegated with other efective way
+ def use
+ @item.use
+ end
+ end
+
+ class MagicItemDecorator < ItemDecorator
+ def price
+ @item.price * 3
+ end
+
+ def description
+ @item.description + "Magic"
+ end
+ end
+
+ class MasterpieceItemDecorator < ItemDecorator
+ def price
+ @item.price * 2
+ end
+
+ def description
+ @item.description + "Masterpiece"
+ end
+ end
+
+ class Item
+ attr_reader :price, :description
+ def initialize
+ @price = 10
+ @description = "Item "
+ end
+
+ def use
+ "do something"
+ end
+ end
+
+ # Usage
+ item = Item.new
+ magic_item = MagicItemDecorator.new(item)
+ puts magic_item.price
+ # => 30
+ puts magic_item.description
+ # => Item Magic
+
+ masterpiece_item = MasterpieceItemDecorator.new(item)
+ puts masterpiece_item.price
+ # => 20
+ puts masterpiece_item.description
+ # => Item Masterpiece
+
+ # all next lines puts "do something"
+ item.use
+ magic_item.use
+ masterpiece_item.use
+ ```
+
+**[Back to top](#table-of-contents)**
+
+## Facade
+ - The goal of the Facade Pattern is to provide a unified interface to a set of interfaces in a subsystem. This means you'd just have some object that can send back other objects.[[link](#facade)]
+
+ ```ruby
+ class Hero
+ attr_reader :name
+
+ def initialize(name)
+ @name = name
+ end
+
+ def join(level)
+ puts "#{self.name} join #{level}\n"
+ end
+
+ def attack(enemy)
+ puts "#{self.name} kick #{enemy}\n"
+ end
+ end
+
+ class Enemy
+ attr_reader :name
+
+ def initialize(name)
+ @name = name
+ end
+
+ def dead(hero)
+ puts "#{self.name} killed by #{hero}"
+ end
+ end
+
+ class Level
+ attr_reader :stage
+
+ def initialize(stage)
+ @stage = stage
+ end
+
+ def to_s
+ stage
+ end
+ end
+
+ class GameFacade
+ attr_reader :hero, :enemy, :level
+
+ def initialize
+ @hero = Hero.new('Sonic')
+ @enemy = Enemy.new('Eggman')
+ @level = Level.new('Green Hill')
+ end
+
+ def start_game
+ hero.join(level)
+ hero.attack(enemy.name)
+ enemy.dead(hero.name)
+ end
+ end
+
+ game = GameFacade.new
+ game.start_game
+ # => Sonic join Green Hill
+ # Sonic kick Eggman
+ # Eggman killed by Sonic
+ ```
+
+**[Back to top](#table-of-contents)**
+
+## Factory
+ - Define an interface for creating an object, but let subclasses decide which class to instantiate.[[link](#factory)]
+
+ ```ruby
+ class Party
+ attr_reader :members
+ def initialize(factory)
+ @members = []
+ @factory = factory
+ end
+
+ def add_warriors(n)
+ n.times{ @members << @factory.create_warrior }
+ end
+
+ def add_mages(n)
+ n.times{ @members << @factory.create_mage }
+ end
+ end
+
+ class HeroFactory
+ def create_warrior
+ Warrior.new
+ end
+
+ def create_mage
+ Mage.new
+ end
+ end
+
+ class Hero
+ def initialize
+ end
+ end
+
+ class Warrior < Hero
+ end
+
+ class Mage < Hero
+ end
+
+ # Usage
+ party = Party.new(HeroFactory.new)
+ party.add_warriors(3)
+ party.add_mages(2)
+ puts party.members.size
+ # => 5
+ puts party.members.count{ |member| member.class == "Mage" }
+ # => 2
+ ```
+
+**[Back to top](#table-of-contents)**
+
+## Interpreter
+ - This pattern provides an interpreter to deal with an abstract language. Using classes we can understand the inputs for parse them.[[link](#interpreter)]
+
+ ```ruby
+ class Word
+ def initialize(value)
+ @value = value
+ end
+
+ def execute
+ @value
+ end
+ end
+
+ class Plus
+ def initialize(first, second)
+ @first = first
+ @second = second
+ end
+
+ def execute
+ @first.execute + @second.execute
+ end
+ end
+
+ class Minus
+ def initialize(first, second)
+ @first = first
+ @second = second
+ end
+
+ def execute
+ index = @first.execute =~ /#{@second.execute}/
+ second_index = index + @second.execute.length
+ @first.execute[0,index] + @first.execute[second_index..-1]
+ end
+ end
+
+ class Interpreter
+ def self.parse(input)
+ @waiting_second_word = false
+ words = []
+ operations = []
+ input.split.each_with_index do |value|
+ if value =~ /^[^+-].*/ && !@waiting_second_word
+ words << Word.new(value)
+ else
+ if symbol = operations.pop()
+ first = words.size > 1 ? Word.new(words.map(&:execute).join(" ")) :
+ words.pop
+ second = Word.new(value)
+ case symbol
+ when /\A\+/
+ words << Word.new(Plus.new(first, second).execute)
+ when /\A\-/
+ words << Word.new(Minus.new(first, second).execute)
+ end
+ @waiting_second_word = false
+ else
+ @waiting_second_word = true
+ operations << value
+ end
+ end
+ end
+ words.pop.execute
+ end
+ end
+
+ puts Interpreter.parse("NA + NA + NA + BATMAN")
+ #=> NANANABATMAN
+
+ puts Interpreter.parse("you know nothing Jon Snow - nothing")
+ #=> you know Jon Snow
+
+ puts Interpreter.parse("hello + world - llowo")
+ #=>herld
+ ```
+
+**[Back to top](#table-of-contents)**
+
+## Iterator
+ - Iterator helps you to iterate through a complex object using an iterator method.[[link](#iterator)]
+
+ ```ruby
+ class Parent
+ attr_reader :first_name
+
+ def initialize(first_name, gender)
+ @first_name = first_name
+ @gender = gender
+ end
+ end
+
+ class Child < Parent
+ end
+
+ class Family
+ def initialize(surname)
+ @surname = surname
+ @children = []
+ end
+
+ def add_father(first_name)
+ @father = Parent.new first_name, "M"
+ end
+
+ def add_mother(first_name)
+ @mother = Parent.new first_name, "F"
+ end
+
+ def add_child(first_name, gender)
+ @children << Child.new(first_name, gender)
+ end
+
+ def each_member
+ [@father, @mother, @children].flatten.each do |member|
+ yield member
+ end
+ end
+ end
+
+ # Usage
+ family = Family.new "Jackson"
+ family.add_father("Robert")
+ family.add_mother("Susan")
+ family.add_child("Lucas", "M")
+ family.add_child("James", "M")
+ family.add_child("Rose", "F")
+ family.each_member{ |member| puts member.first_name }
+ # => Robert
+ # Susan
+ # Lucas
+ # James
+ # Rose
+ ```
+
+**[Back to top](#table-of-contents)**
+
+## Observer
+ - Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.[[link](#observer)]
+
+ ```ruby
+ module Observable
+ attr_reader :observers
+
+ def initialize(attrs = {})
+ @observers = []
+ end
+
+ def add_observer(observer)
+ @observers << observer
+ end
+
+ def notify_observers
+ @observers.each{ |observer| observer.update }
+ end
+ end
+
+ class Tile
+ include Observable
+
+ def initialize(attrs = {})
+ super
+ @cursed = attrs.fetch(:cursed, false)
+ end
+
+ def cursed?
+ @cursed
+ end
+
+ def activate_curse
+ notify_observers
+ end
+ end
+
+ class Hero
+ attr_reader :health
+
+ def initialize
+ @cursed = false
+ @health = 10
+ end
+
+ def damage(hit)
+ @health -= hit
+ end
+
+ def cursed?
+ @cursed
+ end
+
+ def discover(tile)
+ if tile.cursed?
+ @cursed = true
+ tile.add_observer(self)
+ end
+ end
+
+ def update
+ damage(4)
+ end
+ end
+
+ # Usage
+ hero = Hero.new
+ tile = Tile.new cursed: true
+ hero.discover(tile)
+ tile.activate_curse
+ puts hero.health
+ # => 6
+ puts hero.cursed?
+ # => true
+ ```
+
+**[Back to top](#table-of-contents)**
+
+## Proxy
+ - Provide a surrogate or placeholder for another object to control access to it.[[link](#proxy)]
+
+ ```ruby
+ require 'forwardable'
+
+ class Hero
+ attr_accessor :keywords
+
+ def initialize
+ @keywords = []
+ end
+ end
+
+ class ComputerProxy
+ # Forwardable allows objects to run methods on behalf
+ # of it's members, in this case the Computer object
+ extend Forwardable
+
+ # We delegate the ComputerProxy's use of
+ # the Computer object's add method
+ def_delegators :real_object, :add
+
+ def initialize(hero)
+ @hero = hero
+ end
+
+ def execute
+ check_access
+ real_object.execute
+ end
+
+ def check_access
+ unless @hero.keywords.include?(:computer)
+ raise "You have no access"
+ end
+ end
+
+ def real_object
+ @real_object ||= Computer.new
+ end
+ end
+
+ class Computer
+ def initialize
+ @queue = []
+ end
+
+ def add(command)
+ @queue << command
+ end
+
+ def execute
+ "executing commands"
+ end
+ end
+
+ # Usage
+ hero = Hero.new
+ proxy = ComputerProxy.new(hero)
+ proxy.add("some command")
+ proxy.execute
+ # => raise error
+ hero.keywords << :computer
+ proxy.execute
+ # => executing commands
+ ```
+
+**[Back to top](#table-of-contents)**
+
+## Singleton
+ - Define a unique instance of an object.[[link](#singleton)]
+
+ ```ruby
+ class HeroFactory
+ @@instance = nil
+
+ def self.instance
+ @@instance ||= HeroFactory.send(:new)
+ end
+
+ def create_warrior
+ Warrior.new
+ end
+
+ def create_mage
+ Mage.new
+ end
+
+ private_class_method :new
+ end
+
+ # Usage
+ factory = HeroFactory.instance
+ another_factory = HeroFactory.instance
+ puts factory == another_factory
+ # => true
+ HeroFactory.new
+ # => Raise Exception
+ ```
+
+**[Back to top](#table-of-contents)**
+
+## State
+ - This pattern tries to simplify complicated control flows changing an object's behavior dynamically.[[link](#state)]
+
+ ```ruby
+ class Operation
+ attr_reader :state
+ def initialize
+ @state = OperationOpenState.new
+ end
+
+ def trigger(state)
+ @state = @state.next(state)
+ end
+ end
+
+ class OperationOpenState
+ def next(state)
+ if valid?(state)
+ OperationPendingPaymentState.new
+ else
+ raise IllegalStateJumpError
+ end
+ end
+
+ def valid?(state)
+ state == :pending_payment
+ end
+ end
+
+ class OperationPendingPaymentState
+ def next(state)
+ OperationConfirmState.new if valid?(state)
+ end
+
+ def valid?(state)
+ state == :confirm
+ end
+ end
+ class IllegalStateJumpError < StandardError; end
+ class OperationConfirmState; end
+
+ #Usage
+ operation = Operation.new
+ puts operation.state.class
+ #=> OperationOpenState
+ operation.trigger :pending_payment
+ puts operation.state.class
+ #=> OperationPendingPaymentState
+ operation.trigger :confirm
+ puts operation.state.class
+ #=> OperationConfirmState
+
+ operation = Operation.new
+ operation.trigger :confirm
+ #=> raise IllegalStateJumpError
+ ```
+
+**[Back to top](#table-of-contents)**
+
+## Strategy
+ - Define a family of algorithms, encapsulate each one, and make them interchangeable.[[link](#strategy)]
+
+ ```ruby
+ class Hero
+ attr_reader :damage, :health, :skills
+ attr_accessor :printer
+
+ def initialize(printer)
+ @damage = 10
+ @health = 5
+ @printer = printer
+ @skills = [:stealth, :driving, :intimidation]
+ end
+
+ def print_stats
+ if block_given?
+ yield(damage, health, skills)
+ else
+ printer.print(damage, health, skills)
+ end
+ end
+ end
+
+ class BattleStats
+ def print(damage, health, skills)
+ "Damage: #{damage}\nHealth: #{health}"
+ end
+ end
+
+ class SkillStats
+ def print(damage, health, skills)
+ skills.inject(""){ |result, skill| result + skill.to_s.capitalize + "\n" }
+ end
+ end
+
+ # Usage
+ Hero.new(BattleStats.new).print_stats
+ # => Damage: 10
+ # Health: 5
+
+ Hero.new(SkillStats.new).print_stats
+ # => Stealth
+ # Driving
+ # Intimidation
+
+ Hero.new(any_printer).print_stats do |damage, health, skills|
+ "Looks: I'm printing a customize message about my hero with damage #{damage} and number of skills: #{skills.size}"
+ end
+ ```
+
+**[Back to top](#table-of-contents)**
+
+## Template
+ - Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template methods lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.[[link](#template)]
+
+ ```ruby
+ class Hero
+ attr_reader :damage, :abilities
+
+ def initialize
+ @damage = damage_rating
+ @abilities = occupation_abilities
+ end
+
+ def greet
+ greeting = ["Hello"]
+ greeting << unique_greeting_line
+ greeting
+ end
+
+ def unique_greeting_line
+ raise "You must define unique_greeting_line"
+ end
+
+ def damage_rating
+ 10
+ end
+
+ def occupation_abilities
+ []
+ end
+
+ def attack
+ "Atack dealing #{damage} damage"
+ end
+ end
+
+ class Warrior < Hero
+ def damage_rating
+ 15
+ end
+
+ def occupation_abilities
+ [:strike]
+ end
+
+ def unique_greeting_line
+ "Warrior is ready to fight!"
+ end
+ end
+
+ class Mage < Hero
+ def damage_rating
+ 7
+ end
+
+ def occupation_abilities
+ [:magic_spell]
+ end
+
+ def unique_greeting_line
+ "Mage is ready to make powerful spells!"
+ end
+ end
+ ```
+
+**[Back to top](#table-of-contents)**
diff --git a/command.rb b/command.rb
index ef2ece9..f18d759 100644
--- a/command.rb
+++ b/command.rb
@@ -4,6 +4,7 @@ class Turn
def initialize
@commands = []
end
+
def run_command(command)
command.execute
@commands << command
@@ -15,7 +16,8 @@ def undo_command
end
class Hero
- attr_reader :money, :health
+ attr_accessor :money, :health
+
def initialize
@money = 0
@health = 100
@@ -63,4 +65,4 @@ def unexecute
# => 10
turn.undo_command
puts hero.money
-# => 0
\ No newline at end of file
+# => 0
diff --git a/composite.rb b/composite.rb
index e904629..7f23581 100644
--- a/composite.rb
+++ b/composite.rb
@@ -37,16 +37,16 @@ def initialize
# Usage
quest1 = Quest.new
-quest1 << MonsterTask
-quest1 << PuzzleTask
+quest1 << MonsterTask.new
+quest1 << PuzzleTask.new
puts quest1.reward
# => 300
quest2 = Quest.new
-quest2 << MonsterTask
-quest2 << PuzzleTask
+quest2 << MonsterTask.new
+quest2 << PuzzleTask.new
megaquest = MegaQuest.new
megaquest << quest1
megaquest << quest2
puts megaquest.reward
-# => 600
\ No newline at end of file
+# => 600
diff --git a/decorator.rb b/decorator.rb
index e2b1d7a..f7714b8 100644
--- a/decorator.rb
+++ b/decorator.rb
@@ -1,4 +1,4 @@
-# Attach additional responsabilities to an object dinamically. Decorators
+# Attach additional responsibilities to an object dynamically. Decorators
# provide a flexible alternative to subclassing for extending functionality
class ItemDecorator
def initialize(item)
@@ -44,13 +44,13 @@ def use
# Usage
item = Item.new
-magic_item = MagicItemDecorator(item)
+magic_item = MagicItemDecorator.new(item)
puts magic_item.price
# => 30
puts magic_item.description
# => Item Magic
-masterpiece_item = MasterpieceItemDecorator(item)
+masterpiece_item = MasterpieceItemDecorator.new(item)
puts masterpiece_item.price
# => 20
puts masterpiece_item.description
@@ -59,4 +59,4 @@ def use
# all next lines puts "do something"
item.use
magic_item.use
-masterpiece_item.use
\ No newline at end of file
+masterpiece_item.use
diff --git a/facade.rb b/facade.rb
new file mode 100644
index 0000000..a46dec7
--- /dev/null
+++ b/facade.rb
@@ -0,0 +1,61 @@
+class Hero
+ attr_reader :name
+
+ def initialize(name)
+ @name = name
+ end
+
+ def join(level)
+ puts "#{self.name} join #{level}\n"
+ end
+
+ def attack(enemy)
+ puts "#{self.name} kick #{enemy}\n"
+ end
+end
+
+class Enemy
+ attr_reader :name
+
+ def initialize(name)
+ @name = name
+ end
+
+ def dead(hero)
+ puts "#{self.name} killed by #{hero}"
+ end
+end
+
+class Level
+ attr_reader :stage
+
+ def initialize(stage)
+ @stage = stage
+ end
+
+ def to_s
+ stage
+ end
+end
+
+class GameFacade
+ attr_reader :hero, :enemy, :level
+
+ def initialize
+ @hero = Hero.new('Sonic')
+ @enemy = Enemy.new('Eggman')
+ @level = Level.new('Green Hill')
+ end
+
+ def start_game
+ hero.join(level)
+ hero.attack(enemy.name)
+ enemy.dead(hero.name)
+ end
+end
+
+game = GameFacade.new
+game.start_game
+# => Sonic join Green Hill
+# Sonic kick Eggman
+# Eggman killed by Sonic
\ No newline at end of file
diff --git a/interpreter.rb b/interpreter.rb
new file mode 100644
index 0000000..fee34ee
--- /dev/null
+++ b/interpreter.rb
@@ -0,0 +1,73 @@
+#This pattern provides an interpreter to deal with an abstract language. Using classes we can understand the inputs for parse them.
+class Word
+ def initialize(value)
+ @value = value
+ end
+
+ def execute
+ @value
+ end
+end
+
+class Plus
+ def initialize(first, second)
+ @first = first
+ @second = second
+ end
+
+ def execute
+ @first.execute + @second.execute
+ end
+end
+
+class Minus
+ def initialize(first, second)
+ @first = first
+ @second = second
+ end
+
+ def execute
+ index = @first.execute =~ /#{@second.execute}/
+ second_index = index + @second.execute.length
+ @first.execute[0,index] + @first.execute[second_index..-1]
+ end
+end
+
+class Interpreter
+ def self.parse(input)
+ @waiting_second_word = false
+ words = []
+ operations = []
+ input.split.each_with_index do |value|
+ if value =~ /^[^+-].*/ && !@waiting_second_word
+ words << Word.new(value)
+ else
+ if symbol = operations.pop()
+ first = words.size > 1 ? Word.new(words.map(&:execute).join(" ")) :
+ words.pop
+ second = Word.new(value)
+ case symbol
+ when /\A\+/
+ words << Word.new(Plus.new(first, second).execute)
+ when /\A\-/
+ words << Word.new(Minus.new(first, second).execute)
+ end
+ @waiting_second_word = false
+ else
+ @waiting_second_word = true
+ operations << value
+ end
+ end
+ end
+ words.pop.execute
+ end
+end
+
+puts Interpreter.parse("NA + NA + NA + BATMAN")
+#=> NANANABATMAN
+
+puts Interpreter.parse("you know nothing Jon Snow - nothing")
+#=> you know Jon Snow
+
+puts Interpreter.parse("hello + world - llowo")
+#=>herld
\ No newline at end of file
diff --git a/iterator.rb b/iterator.rb
index 80bb1d6..de96be6 100644
--- a/iterator.rb
+++ b/iterator.rb
@@ -1,5 +1,5 @@
# Iterator helps you to iterate through a complex object using
-# an interator method
+# an iterator method
class Parent
attr_reader :first_name
@@ -28,7 +28,7 @@ def add_mother(first_name)
end
def add_child(first_name, gender)
- @children << Child.new first_name, gender
+ @children << Child.new(first_name, gender)
end
def each_member
@@ -50,4 +50,4 @@ def each_member
# Susan
# Lucas
# James
-# Rose
\ No newline at end of file
+# Rose
diff --git a/observer.rb b/observer.rb
index 4329918..381d305 100644
--- a/observer.rb
+++ b/observer.rb
@@ -23,7 +23,7 @@ class Tile
def initialize(attrs = {})
super
- @cursed = attrs.fetch(:cursed, :false)
+ @cursed = attrs.fetch(:cursed, false)
end
def cursed?
@@ -71,4 +71,4 @@ def update
puts hero.health
# => 6
puts hero.cursed?
-# => true
\ No newline at end of file
+# => true
diff --git a/proxy.rb b/proxy.rb
index 64dd523..4b98a11 100644
--- a/proxy.rb
+++ b/proxy.rb
@@ -1,3 +1,5 @@
+require 'forwardable'
+
# Provide a surrogate or placeholder for another object to control
# access to it
class Hero
@@ -9,8 +11,12 @@ def initialize
end
class ComputerProxy
+ # Forwardable allows objects to run methods on behalf
+ # of it's members, in this case the Computer object
extend Forwardable
+ # We delegate the ComputerProxy's use of
+ # the Computer object's add method
def_delegators :real_object, :add
def initialize(hero)
@@ -37,7 +43,7 @@ class Computer
def initialize
@queue = []
end
-
+
def add(command)
@queue << command
end
@@ -55,4 +61,4 @@ def execute
# => raise error
hero.keywords << :computer
proxy.execute
-# => executing commands
\ No newline at end of file
+# => executing commands
diff --git a/state.rb b/state.rb
new file mode 100644
index 0000000..57ed48d
--- /dev/null
+++ b/state.rb
@@ -0,0 +1,52 @@
+#This pattern try to simplify complicate control flows changing an object's behaviour dynamically
+class Operation
+ attr_reader :state
+ def initialize
+ @state = OperationOpenState.new
+ end
+
+ def trigger(state)
+ @state = @state.next(state)
+ end
+end
+
+class OperationOpenState
+ def next(state)
+ if valid?(state)
+ OperationPendingPaymentState.new
+ else
+ raise IllegalStateJumpError
+ end
+ end
+
+ def valid?(state)
+ state == :pending_payment
+ end
+end
+
+class OperationPendingPaymentState
+ def next(state)
+ OperationConfirmState.new if valid?(state)
+ end
+
+ def valid?(state)
+ state == :confirm
+ end
+end
+class IllegalStateJumpError < StandardError; end
+class OperationConfirmState; end
+
+#Usage
+operation = Operation.new
+puts operation.state.class
+#=> OperationOpenState
+operation.trigger :pending_payment
+puts operation.state.class
+#=> OperationPendingPaymentState
+operation.trigger :confirm
+puts operation.state.class
+#=> OperationConfirmState
+
+operation = Operation.new
+operation.trigger :confirm
+#=> raise IllegalStateJumpError
diff --git a/strategy.rb b/strategy.rb
index 01b78f6..bb90cbe 100644
--- a/strategy.rb
+++ b/strategy.rb
@@ -34,18 +34,15 @@ def print(damage, health, skills)
end
# Usage
-Hero.new(BattleStats.new)
-Hero.print_stats
+Hero.new(BattleStats.new).print_stats
# => Damage: 10
# Health: 5
-Hero.new(SkillStats.new)
-Hero.print_stats
+Hero.new(SkillStats.new).print_stats
# => Stealth
# Driving
# Intimidation
-Hero.new(any_printer)
-Hero.print_stats do |damage, health, skills|
+Hero.new(any_printer).print_stats do |damage, health, skills|
"Looks: I'm printing a customize message about my hero with damage #{damage} and number of skills: #{skills.size}"
-end
\ No newline at end of file
+end