From 49e857d63547fd8b116ad99b372a343f9a678f12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20L=C3=B3pez=20Montalvo?= Date: Mon, 6 Apr 2015 10:28:29 -0500 Subject: [PATCH 01/26] Update README.md --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 2586809..4480937 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,2 @@ # 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! From b2ade9904e2086153081066a357632366fb86444 Mon Sep 17 00:00:00 2001 From: Dan Fockler Date: Mon, 6 Apr 2015 09:13:58 -0700 Subject: [PATCH 02/26] Small note about how Forwardable works --- proxy.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/proxy.rb b/proxy.rb index 64dd523..a288360 100644 --- a/proxy.rb +++ b/proxy.rb @@ -9,8 +9,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) @@ -55,4 +59,4 @@ def execute # => raise error hero.keywords << :computer proxy.execute -# => executing commands \ No newline at end of file +# => executing commands From f17ca9fd29bdec331bee41fdb3608b0c234c64da Mon Sep 17 00:00:00 2001 From: Julio Lopez Date: Wed, 6 May 2015 09:44:36 -0500 Subject: [PATCH 03/26] update readme --- README.md | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/README.md b/README.md index 4480937..8f81b93 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,99 @@ # ruby-patterns Examples of Patterns in Ruby + +## Table of Contents + + 1. [Adapter](#adapter) + 1. [Builder](#builder) + 1. [Command](#command) + 1. [Composite](#composite) + 1. [Decorator](#decorator) + 1. [Factory](#factory) + 1. [Iterator](#iterator) + 1. [Observer](#observer) + 1. [Proxy](#proxy) + 1. [Singleton](#singleton) + 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 + + ```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 + ``` \ No newline at end of file From de2bb18188e4ac9f7d94ef3b60c1c14f5823b905 Mon Sep 17 00:00:00 2001 From: Julio Lopez Date: Wed, 6 May 2015 09:56:36 -0500 Subject: [PATCH 04/26] update readme --- README.md | 665 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 664 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8f81b93..9eaa5e7 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Examples of Patterns in Ruby 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 + - Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces. ```ruby class Quest @@ -96,4 +96,667 @@ Examples of Patterns in Ruby 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. + + ```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. + + ```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_reader :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 intro tree structures to represent part-whole hierarchies. + + ```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 + quest1 << PuzzleTask + puts quest1.reward + # => 300 + + quest2 = Quest.new + quest2 << MonsterTask + quest2 << PuzzleTask + megaquest = MegaQuest.new + megaquest << quest1 + megaquest << quest2 + puts megaquest.reward + # => 600 + ``` + +**[Back to top](#table-of-contents)** + +## Decorator + - Attach additional responsabilities to an object dinamically. Decorators provide a flexible alternative to subclassing for extending functionality. + + ```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(item) + puts magic_item.price + # => 30 + puts magic_item.description + # => Item Magic + + masterpiece_item = MasterpieceItemDecorator(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)** + +## Factory + - Define an interface for creating an object, but let subclasses decide which class to instantiate. + + ```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)** + +## Iterator + - Iterator helps you to iterate through a complex object using an interator method. + + ```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. + + ```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. + + ```ruby + 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 an unique instance of an object. + + ```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)** + +## Strategy + - Define a family of algorithms, encapsulate each one, and make them interchangeable. + + ```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) + Hero.print_stats + # => Damage: 10 + # Health: 5 + + Hero.new(SkillStats.new) + Hero.print_stats + # => Stealth + # Driving + # Intimidation + + Hero.new(any_printer) + Hero.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. + + ```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 ``` \ No newline at end of file From 5ff8e8226220d342d1dedc5b140996a7b638b503 Mon Sep 17 00:00:00 2001 From: Julio Lopez Date: Wed, 6 May 2015 10:05:03 -0500 Subject: [PATCH 05/26] update readme --- README.md | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 9eaa5e7..3d2d4cf 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Examples of Patterns in Ruby 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. + - 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 @@ -101,7 +101,7 @@ Examples of Patterns in Ruby **[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. + - 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 @@ -153,7 +153,7 @@ Examples of Patterns in Ruby **[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. + - 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 @@ -225,7 +225,7 @@ Examples of Patterns in Ruby **[Back to top](#table-of-contents)** ## Composite - - Composition over inheritance. Compose objects intro tree structures to represent part-whole hierarchies. + - Composition over inheritance. Compose objects intro tree structures to represent part-whole hierarchies.[[link](#composite)] ```ruby class CompositeQuest @@ -284,7 +284,7 @@ Examples of Patterns in Ruby **[Back to top](#table-of-contents)** ## Decorator - - Attach additional responsabilities to an object dinamically. Decorators provide a flexible alternative to subclassing for extending functionality. + - Attach additional responsabilities to an object dinamically. Decorators provide a flexible alternative to subclassing for extending functionality.[[link](#decorator)] ```ruby class ItemDecorator @@ -352,7 +352,7 @@ Examples of Patterns in Ruby **[Back to top](#table-of-contents)** ## Factory - - Define an interface for creating an object, but let subclasses decide which class to instantiate. + - Define an interface for creating an object, but let subclasses decide which class to instantiate.[[link](#factory)] ```ruby class Party @@ -405,7 +405,7 @@ Examples of Patterns in Ruby **[Back to top](#table-of-contents)** ## Iterator - - Iterator helps you to iterate through a complex object using an interator method. + - Iterator helps you to iterate through a complex object using an interator method.[[link](#iterator)] ```ruby class Parent @@ -463,7 +463,7 @@ Examples of Patterns in Ruby **[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. + - 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 @@ -541,7 +541,7 @@ Examples of Patterns in Ruby **[Back to top](#table-of-contents)** ## Proxy - - Provide a surrogate or placeholder for another object to control access to it. + - Provide a surrogate or placeholder for another object to control access to it.[[link](#proxy)] ```ruby class Hero @@ -609,7 +609,7 @@ Examples of Patterns in Ruby **[Back to top](#table-of-contents)** ## Singleton - - Define an unique instance of an object. + - Define an unique instance of an object.[[link](#singleton)] ```ruby class HeroFactory @@ -642,7 +642,7 @@ Examples of Patterns in Ruby **[Back to top](#table-of-contents)** ## Strategy - - Define a family of algorithms, encapsulate each one, and make them interchangeable. + - Define a family of algorithms, encapsulate each one, and make them interchangeable.[[link](#strategy)] ```ruby class Hero @@ -698,7 +698,7 @@ Examples of Patterns in Ruby **[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. + - 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 @@ -759,4 +759,5 @@ Examples of Patterns in Ruby "Mage is ready to make powerful spells!" end end - ``` \ No newline at end of file + ``` + **[Back to top](#table-of-contents)** \ No newline at end of file From d723b002ad62d5735e3ac8067a31626302413557 Mon Sep 17 00:00:00 2001 From: Julio Lopez Date: Wed, 6 May 2015 10:50:33 -0500 Subject: [PATCH 06/26] added state pattern --- README.md | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- state.rb | 48 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 state.rb diff --git a/README.md b/README.md index 3d2d4cf..427538c 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ Examples of Patterns in Ruby 1. [Observer](#observer) 1. [Proxy](#proxy) 1. [Singleton](#singleton) + 1. [State](#state) 1. [Strategy](#strategy) 1. [Template](#template) @@ -641,6 +642,61 @@ Examples of Patterns in Ruby **[Back to top](#table-of-contents)** +## State + - This pattern try to simplify complicate control flows changing an object's behaviour dynamically + + ```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) + valid?(state) ? OperationPendingPaymentState.new : raise IllegalStateJumpError + 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)] @@ -760,4 +816,4 @@ Examples of Patterns in Ruby end end ``` - **[Back to top](#table-of-contents)** \ No newline at end of file +**[Back to top](#table-of-contents)** \ No newline at end of file diff --git a/state.rb b/state.rb new file mode 100644 index 0000000..fdaafbc --- /dev/null +++ b/state.rb @@ -0,0 +1,48 @@ +#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) + valid?(state) ? OperationPendingPaymentState.new : raise IllegalStateJumpError + 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 \ No newline at end of file From 7e4ec01a3a99ddeb2fe5b92d7f688c966b97e0d9 Mon Sep 17 00:00:00 2001 From: Julio Lopez Date: Wed, 6 May 2015 10:55:49 -0500 Subject: [PATCH 07/26] added state link to readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 427538c..effae8e 100644 --- a/README.md +++ b/README.md @@ -643,7 +643,7 @@ Examples of Patterns in Ruby **[Back to top](#table-of-contents)** ## State - - This pattern try to simplify complicate control flows changing an object's behaviour dynamically + - This pattern try to simplify complicate control flows changing an object's behaviour dynamically.[[link](#state)] ```ruby class Operation From af49dc16bcb3f0aecfda5f70da3306069b5075fc Mon Sep 17 00:00:00 2001 From: Tyler Lyman Date: Fri, 8 May 2015 13:57:00 -0600 Subject: [PATCH 08/26] Fixed typos in documentation --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index effae8e..ced4f34 100644 --- a/README.md +++ b/README.md @@ -285,7 +285,7 @@ Examples of Patterns in Ruby **[Back to top](#table-of-contents)** ## Decorator - - Attach additional responsabilities to an object dinamically. Decorators provide a flexible alternative to subclassing for extending functionality.[[link](#decorator)] + - Attach additional responsabilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.[[link](#decorator)] ```ruby class ItemDecorator @@ -610,7 +610,7 @@ Examples of Patterns in Ruby **[Back to top](#table-of-contents)** ## Singleton - - Define an unique instance of an object.[[link](#singleton)] + - Define a unique instance of an object.[[link](#singleton)] ```ruby class HeroFactory @@ -643,7 +643,7 @@ Examples of Patterns in Ruby **[Back to top](#table-of-contents)** ## State - - This pattern try to simplify complicate control flows changing an object's behaviour dynamically.[[link](#state)] + - This pattern tries to simplify complicated control flows changing an object's behavior dynamically.[[link](#state)] ```ruby class Operation From 6de1249ec93977f6ad4abed6621fa2d57dfa83e4 Mon Sep 17 00:00:00 2001 From: Julio Lopez Date: Fri, 8 May 2015 19:36:52 -0500 Subject: [PATCH 09/26] fixed typo --- README.md | 2 +- decorator.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ced4f34..a1f9f57 100644 --- a/README.md +++ b/README.md @@ -285,7 +285,7 @@ Examples of Patterns in Ruby **[Back to top](#table-of-contents)** ## Decorator - - Attach additional responsabilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.[[link](#decorator)] + - Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.[[link](#decorator)] ```ruby class ItemDecorator diff --git a/decorator.rb b/decorator.rb index e2b1d7a..c391d79 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) From b420702ba76267030b9bfee91f91aba0efe5b817 Mon Sep 17 00:00:00 2001 From: Morgan Owens Date: Mon, 1 Jun 2015 12:57:46 -0400 Subject: [PATCH 10/26] fixed typo --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index a1f9f57..a1a95db 100644 --- a/README.md +++ b/README.md @@ -23,10 +23,10 @@ Examples of Patterns in Ruby ```ruby class Quest attr_accessor :difficulty, :hero - + def initialize(difficulty) @difficulty = difficulty - @hero = nil + @hero = nil end def finish @@ -226,7 +226,7 @@ Examples of Patterns in Ruby **[Back to top](#table-of-contents)** ## Composite - - Composition over inheritance. Compose objects intro tree structures to represent part-whole hierarchies.[[link](#composite)] + - Composition over inheritance. Compose objects into tree structures to represent part-whole hierarchies.[[link](#composite)] ```ruby class CompositeQuest @@ -558,7 +558,7 @@ Examples of Patterns in Ruby # of it's members, in this case the Computer object extend Forwardable - # We delegate the ComputerProxy's use of + # We delegate the ComputerProxy's use of # the Computer object's add method def_delegators :real_object, :add @@ -586,7 +586,7 @@ Examples of Patterns in Ruby def initialize @queue = [] end - + def add(command) @queue << command end @@ -816,4 +816,4 @@ Examples of Patterns in Ruby end end ``` -**[Back to top](#table-of-contents)** \ No newline at end of file +**[Back to top](#table-of-contents)** From f590851712e61de4c7cfc25b62c7c414365e4975 Mon Sep 17 00:00:00 2001 From: Tadas Sce Date: Fri, 26 Jun 2015 14:54:05 +0300 Subject: [PATCH 11/26] Use attr_accessor Otherwise `+=` doesn't work --- README.md | 4 +++- command.rb | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a1a95db..b47114e 100644 --- a/README.md +++ b/README.md @@ -161,6 +161,7 @@ Examples of Patterns in Ruby def initialize @commands = [] end + def run_command(command) command.execute @commands << command @@ -172,7 +173,8 @@ Examples of Patterns in Ruby end class Hero - attr_reader :money, :health + attr_accessor :money, :health + def initialize @money = 0 @health = 100 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 From bc0b21ff8a54c95aaa9a73342f59b75a205bb5d5 Mon Sep 17 00:00:00 2001 From: Tadas Sce Date: Fri, 26 Jun 2015 15:00:12 +0300 Subject: [PATCH 12/26] Fix composite We need to append instances of tasks here --- README.md | 8 ++++---- composite.rb | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index b47114e..d5ddb01 100644 --- a/README.md +++ b/README.md @@ -269,14 +269,14 @@ Examples of Patterns in Ruby # 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 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 From cb5d22049159c32e6c58c180a1f57d2ba125961d Mon Sep 17 00:00:00 2001 From: Tadas Sce Date: Fri, 26 Jun 2015 15:01:43 +0300 Subject: [PATCH 13/26] Fix decorator - add missing `new` for init --- README.md | 4 ++-- decorator.rb | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index d5ddb01..ac36fd7 100644 --- a/README.md +++ b/README.md @@ -334,13 +334,13 @@ Examples of Patterns in Ruby # 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 diff --git a/decorator.rb b/decorator.rb index c391d79..f7714b8 100644 --- a/decorator.rb +++ b/decorator.rb @@ -1,4 +1,4 @@ -# Attach additional responsibilities to an object dynamically. 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 From a0f016699d0fb86de5a03f44a1b201aae1e58084 Mon Sep 17 00:00:00 2001 From: Tadas Sce Date: Fri, 26 Jun 2015 15:03:00 +0300 Subject: [PATCH 14/26] Fix iterator `<<` has higher presedence so we need the parenthesis --- README.md | 2 +- iterator.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ac36fd7..5789be1 100644 --- a/README.md +++ b/README.md @@ -438,7 +438,7 @@ Examples of Patterns in Ruby end def add_child(first_name, gender) - @children << Child.new first_name, gender + @children << Child.new(first_name, gender) end def each_member diff --git a/iterator.rb b/iterator.rb index 80bb1d6..dcbb4c0 100644 --- a/iterator.rb +++ b/iterator.rb @@ -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 From 9688e9ea5abadca1367cec23ccdda74bb5f4735e Mon Sep 17 00:00:00 2001 From: Tadas Sce Date: Fri, 26 Jun 2015 15:04:59 +0300 Subject: [PATCH 15/26] Fix observer Probably a typo - `:false` is truthy ;) --- README.md | 2 +- observer.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5789be1..468541c 100644 --- a/README.md +++ b/README.md @@ -490,7 +490,7 @@ Examples of Patterns in Ruby def initialize(attrs = {}) super - @cursed = attrs.fetch(:cursed, :false) + @cursed = attrs.fetch(:cursed, false) end def cursed? 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 From 1dbbbb7438c6770cd89d32ffbdbef3e87d48d673 Mon Sep 17 00:00:00 2001 From: Tadas Sce Date: Fri, 26 Jun 2015 15:06:02 +0300 Subject: [PATCH 16/26] Add missing require in proxy example --- proxy.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/proxy.rb b/proxy.rb index a288360..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 @@ -13,7 +15,7 @@ class ComputerProxy # of it's members, in this case the Computer object extend Forwardable - # We delegate the ComputerProxy's use of + # We delegate the ComputerProxy's use of # the Computer object's add method def_delegators :real_object, :add @@ -41,7 +43,7 @@ class Computer def initialize @queue = [] end - + def add(command) @queue << command end From 34aedbf6233111ed162205ed9247432ea3fcf65d Mon Sep 17 00:00:00 2001 From: Tadas Sce Date: Fri, 26 Jun 2015 15:15:52 +0300 Subject: [PATCH 17/26] Fix state Wrong precedence again. So either this or parenthesis for raise --- README.md | 6 +++++- state.rb | 8 ++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 468541c..f1958fd 100644 --- a/README.md +++ b/README.md @@ -661,7 +661,11 @@ Examples of Patterns in Ruby class OperationOpenState def next(state) - valid?(state) ? OperationPendingPaymentState.new : raise IllegalStateJumpError + if valid?(state) + OperationPendingPaymentState.new + else + raise IllegalStateJumpError + end end def valid?(state) diff --git a/state.rb b/state.rb index fdaafbc..57ed48d 100644 --- a/state.rb +++ b/state.rb @@ -12,7 +12,11 @@ def trigger(state) class OperationOpenState def next(state) - valid?(state) ? OperationPendingPaymentState.new : raise IllegalStateJumpError + if valid?(state) + OperationPendingPaymentState.new + else + raise IllegalStateJumpError + end end def valid?(state) @@ -45,4 +49,4 @@ class OperationConfirmState; end operation = Operation.new operation.trigger :confirm -#=> raise IllegalStateJumpError \ No newline at end of file +#=> raise IllegalStateJumpError From ff360352328258ab2fe54862a62703d04244d5fa Mon Sep 17 00:00:00 2001 From: Tadas Sce Date: Fri, 26 Jun 2015 15:19:05 +0300 Subject: [PATCH 18/26] Fix strategy example --- README.md | 9 +++------ strategy.rb | 11 ++++------- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index f1958fd..a0fddb1 100644 --- a/README.md +++ b/README.md @@ -740,19 +740,16 @@ Examples of Patterns in Ruby 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 ``` 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 From 6dd330411d36f9e712a164ce039f0e2b5cb7e164 Mon Sep 17 00:00:00 2001 From: Julio Lopez Date: Sat, 27 Jun 2015 03:43:00 -0500 Subject: [PATCH 19/26] added fun interpreter pattern --- README.md | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++ interpreter.rb | 73 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 154 insertions(+) create mode 100644 interpreter.rb diff --git a/README.md b/README.md index a0fddb1..4c527fc 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ Examples of Patterns in Ruby 1. [Composite](#composite) 1. [Decorator](#decorator) 1. [Factory](#factory) + 1. [Interpreter](#interpreter) 1. [Iterator](#iterator) 1. [Observer](#observer) 1. [Proxy](#proxy) @@ -407,6 +408,86 @@ Examples of Patterns in Ruby **[Back to top](#table-of-contents)** +## Interpreter + - This pattern provides an interpreter to deal with an abstract language. Using classes we can understand symbols to parse our inputs.[[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 interator method.[[link](#iterator)] diff --git a/interpreter.rb b/interpreter.rb new file mode 100644 index 0000000..a816b7a --- /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 symbols to parse our inputs. +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 From ec7e00984f05dd523bc3026d60ed4e77f83fd46f Mon Sep 17 00:00:00 2001 From: Julio Lopez Date: Sat, 27 Jun 2015 03:46:40 -0500 Subject: [PATCH 20/26] fix typo --- README.md | 2 +- interpreter.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4c527fc..47611a6 100644 --- a/README.md +++ b/README.md @@ -409,7 +409,7 @@ Examples of Patterns in Ruby **[Back to top](#table-of-contents)** ## Interpreter - - This pattern provides an interpreter to deal with an abstract language. Using classes we can understand symbols to parse our inputs.[[link](#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 diff --git a/interpreter.rb b/interpreter.rb index a816b7a..fee34ee 100644 --- a/interpreter.rb +++ b/interpreter.rb @@ -1,4 +1,4 @@ -#This pattern provides an interpreter to deal with an abstract language. Using classes we can understand symbols to parse our inputs. +#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 From 3adae3d41e5568502956102507cb2586b24d34f9 Mon Sep 17 00:00:00 2001 From: Ivan Date: Wed, 28 Oct 2015 00:14:46 +0200 Subject: [PATCH 21/26] fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 47611a6..def5921 100644 --- a/README.md +++ b/README.md @@ -489,7 +489,7 @@ Examples of Patterns in Ruby **[Back to top](#table-of-contents)** ## Iterator - - Iterator helps you to iterate through a complex object using an interator method.[[link](#iterator)] + - Iterator helps you to iterate through a complex object using an iterator method.[[link](#iterator)] ```ruby class Parent From b46773490e5bf0af5285334606e79ec23a88013f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20L=C3=B3pez=20Montalvo?= Date: Sat, 31 Oct 2015 10:51:55 -0500 Subject: [PATCH 22/26] Update iterator.rb --- iterator.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iterator.rb b/iterator.rb index dcbb4c0..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 From 7f251ab8ed1c614802ee6976c9c4e49cf3791f43 Mon Sep 17 00:00:00 2001 From: ID25 Date: Sat, 31 Oct 2015 21:04:53 +0300 Subject: [PATCH 23/26] Added Facade Pattern Example --- README.md | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ facade.rb | 58 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 facade.rb diff --git a/README.md b/README.md index def5921..754aecb 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ Examples of Patterns in Ruby 1. [State](#state) 1. [Strategy](#strategy) 1. [Template](#template) + 1. [Facade](#facade) ## 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)] @@ -900,4 +901,69 @@ Examples of Patterns in Ruby end end ``` + +## 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 + ``` + **[Back to top](#table-of-contents)** diff --git a/facade.rb b/facade.rb new file mode 100644 index 0000000..5237943 --- /dev/null +++ b/facade.rb @@ -0,0 +1,58 @@ +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 From ffe35505d8451bd43c64f1915c906bc91f50ed7e Mon Sep 17 00:00:00 2001 From: Julio Lopez Date: Tue, 1 Dec 2015 21:31:19 -0500 Subject: [PATCH 24/26] added prints of facade pattern --- README.md | 3 +++ facade.rb | 3 +++ 2 files changed, 6 insertions(+) diff --git a/README.md b/README.md index 754aecb..a9def14 100644 --- a/README.md +++ b/README.md @@ -964,6 +964,9 @@ Examples of Patterns in Ruby game = GameFacade.new game.start_game + # => Sonic join Green Hill + # Sonic kick Eggman + # Eggman killed by Sonic ``` **[Back to top](#table-of-contents)** diff --git a/facade.rb b/facade.rb index 5237943..a46dec7 100644 --- a/facade.rb +++ b/facade.rb @@ -56,3 +56,6 @@ def start_game game = GameFacade.new game.start_game +# => Sonic join Green Hill +# Sonic kick Eggman +# Eggman killed by Sonic \ No newline at end of file From 48983c938ad2d1f22f1e79616f49562ff58353ad Mon Sep 17 00:00:00 2001 From: Julio Lopez Date: Tue, 1 Dec 2015 21:50:11 -0500 Subject: [PATCH 25/26] alphabetic order list --- README.md | 138 +++++++++++++++++++++++++++--------------------------- 1 file changed, 70 insertions(+), 68 deletions(-) diff --git a/README.md b/README.md index a9def14..62c1404 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ Examples of Patterns in Ruby 1. [Command](#command) 1. [Composite](#composite) 1. [Decorator](#decorator) + 1. [Facade](#facade) 1. [Factory](#factory) 1. [Interpreter](#interpreter) 1. [Iterator](#iterator) @@ -17,7 +18,6 @@ Examples of Patterns in Ruby 1. [State](#state) 1. [Strategy](#strategy) 1. [Template](#template) - 1. [Facade](#facade) ## 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)] @@ -356,6 +356,75 @@ Examples of Patterns in Ruby **[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)] @@ -902,71 +971,4 @@ Examples of Patterns in Ruby end ``` -## 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)** From 584ae6a77a05f2fefc642f796a526a6d3376bd9d Mon Sep 17 00:00:00 2001 From: Julio Lopez Date: Mon, 22 Feb 2016 19:07:14 -0500 Subject: [PATCH 26/26] added missing require in proxy pattern --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 62c1404..e1497e1 100644 --- a/README.md +++ b/README.md @@ -524,7 +524,7 @@ Examples of Patterns in Ruby input.split.each_with_index do |value| if value =~ /^[^+-].*/ && !@waiting_second_word words << Word.new(value) - else + else if symbol = operations.pop() first = words.size > 1 ? Word.new(words.map(&:execute).join(" ")) : words.pop @@ -698,6 +698,8 @@ Examples of Patterns in Ruby - Provide a surrogate or placeholder for another object to control access to it.[[link](#proxy)] ```ruby + require 'forwardable' + class Hero attr_accessor :keywords