Wednesday, August 27, 2014

Iterator pattern ruby

Iterator is too obvious in ruby, so assume some theoretical example.
class Iterator
  def first; end
  def last; end
  def next; end
  def current; end
  def has_next?; end
end

class InfiniteNumbers < Iterator
  def initialize
    @current = 0
  end
  
  def first
    1
  end
  
  def last
    raise "Infinite number"
  end
  
  def next
    @current += 1
  end
  
  def current
    @current
  end
  
  def has_next?
    true
  end  
end

iterator = InfiniteNumbers.new
puts 100.times.collect { iterator.next }.join(',')

Composite pattern ruby

Class ItemsGroup could be called Composite in current example.
class Component
  attr_reader :data
  
  def initialize(data)
    @data = data
  end
  
  def display
    raise "Implement me"
  end
end

class ItemsGroup < Component
  def initialize
    @children = []
  end
  
  def add_child(child)
    @children << child
  end
  
  def remove_child(child)
    @children.delete(child)
  end
  
  def display
    @children.each do |child|
      child.display
    end
  end
end

class Item < Component
  def display
    puts data.inspect
  end
end

group = ItemsGroup.new
group1 = ItemsGroup.new
group2 = ItemsGroup.new

group1.add_child(Item.new('label'))
group1.add_child(Item.new('input text'))
group2.add_child(Item.new('label'))
group2.add_child(Item.new('input password'))

group.add_child(Item.new("header"))
group.add_child(group1)
group.add_child(group2)
group.add_child(Item.new("submit button"))

group.display

Monday, August 25, 2014

Observer pattern ruby



Current implementation dont have base class for Observers. Observer methods moved to module. This is a basic solution without any checkings.
module ObserverMethods
  def initialize
    @observers = []
  end
  def add_observer(observer)
    @observers << observer
  end
  def delete_observer(observer)
    @observers.delete(observer)
  end
  def notify_observers
    @observers.each do |observer|
      observer.update(self)
    end
  end
end


class Entity
  include ObserverMethods
  
  attr_reader :name, :description
  
  def name=(value)
    @name = value
    notify_observers
  end
  def description=(value)
    @description = value
    notify_observers
  end
end

class TxtObserver
  def update(entity)
    puts "txt: #{entity.name}, #{entity.description}"
  end
end
class TxtConsoleObserver
  def update(entity)
    puts ">> #{entity.name}, #{entity.description}"
  end
end


entity = Entity.new
entity.add_observer(TxtConsoleObserver.new)
entity.add_observer(TxtObserver.new)

entity.name = "Name"
entity.description = "Description"

$ ruby observer.rb 
>> Name, 
txt: Name, 
>> Name, Description
txt: Name, Description

Sunday, August 24, 2014

Strategy pattern ruby

In Ruby implementation base class Strategy could be removed.
class Strategy
  def output(data)
    raise "Implement me"
  end
end

class TxtOutput < Strategy
  def output(data)
    puts data.inspect
  end
end

class ConsoleTxtOutput < Strategy
  def output(data)
    puts ">> #{data.inspect}"
  end
end

class SomeLogic
  attr_accessor :output_formatter
  
  def initialize(output_formatter)
    @output_formatter = output_formatter
  end
  
  def do_some_job
    @data = { "some" => "data", "here" => 10 }
  end
  
  def print_somewhere
    @output_formatter.output(@data)
  end
end

txt_output = TxtOutput.new
console_txt_outut = ConsoleTxtOutput.new

# Specify formatter dynamically
logic = SomeLogic.new(txt_output)
logic.do_some_job
logic.print_somewhere
# Specify formatter dynamically
logic.output_formatter = console_txt_outut
logic.print_somewhere

Saturday, August 23, 2014

Template method pattern ruby



class ReportGenerator
  
  def initialize
    @report = ""
  end
  
  def output
    prepare_header
    prepare_body
    prepare_footer
    @report
  end
  
  def prepare_header
    raise "Prepare header should be implemented"
  end
  def prepare_body
    raise "Prepare body should be implemented"
  end
  def prepare_footer
    raise "Prepare footer should be implemented"
  end
end

class TxtReportGenerator < ReportGenerator
  def prepare_header
    @report << "Txt Report header \n"
  end
  def prepare_body
    @report << "body \n"
  end
  def prepare_footer
    @report << "footer \n"
  end
end

class PdfReportGenerator < ReportGenerator
  def prepare_header
    @report << "Pdf Report header \n"
  end
  def prepare_body
    @report << "some encoded body \n"
  end
  def prepare_footer
    @report << "encoded footer \n"
  end
end

txt = TxtReportGenerator.new
pdf = PdfReportGenerator.new

puts txt.output
puts pdf.output