Skip to content

Instantly share code, notes, and snippets.

@ackintosh
Created May 28, 2013 23:24
Show Gist options
  • Save ackintosh/5666911 to your computer and use it in GitHub Desktop.
Save ackintosh/5666911 to your computer and use it in GitHub Desktop.
Builder pattern in Ruby
# -*- encoding: utf-8 -*-
class Computer
attr_accessor :display, :motherboard
attr_reader :drives
def initialize(display = :crt, motherboard = Motherboard.new, drives = [])
@display = display
@motherboard = motherboard
@drives = drives
end
end
class CPU;end
class BasicCPU < CPU;end
class TurboCPU < CPU;end
class Motherboard
attr_accessor :cpu, :memory_size
def initialize(cpu = BasicCPU.new, memory_size = 1000)
@cpu = cpu
@memory_size = memory_size
end
end
class Drive
attr_reader :type # :hard_disk or :cd or :dvd
attr_reader :size # MB
attr_reader :writable # true if writable
def initialize(type, size, writable)
@type = type
@size = size
@writable = writable
end
end
class LaptopDrive
attr_reader :type # :hard_disk or :cd or :dvd
attr_reader :size # MB
attr_reader :writable # true if writable
def initialize(type, size, writable)
@type = type
@size = size
@writable = writable
end
end
class DesktopComputer < Computer;end
class LaptopComputer < Computer
def initialize(motherboard = Motherboard.new, drives = [])
super(:lcd, motherboard, drives)
end
end
class ComputerBuilder
attr_reader :computer
def turbo(has_turbo_cpu = true)
@computer.motherboard.cpu = TurboCPU.new
end
def memory_size(size_in_mb)
@computer.motherboard.memory_size = size_in_mb
end
def computer
raise "Not enough memory" if @computer.motherboard.memory_size < 250
raise "Too many drives" if @computer.drives.size > 4
hard_disk = @computer.drives.find { |drive| drive.type == :hard_disk }
raise "No hard disk." unless hard_disk
@computer
end
def method_missing(name, *args)
words = name.to_s.split('_')
return super(name, *args) unless words.shift == 'add'
args_index = 0
words.each do |w|
next if w == 'and'
if w == 'cd'
add_cd(args[args_index])
elsif w == 'dvd'
add_dvd(args[args_index])
elsif w == 'harddisk'
add_hard_disk(args[args_index])
else
raise "Unknown drive"
end
args_index += 1
end
end
end
class DesktopBuilder < ComputerBuilder
def initialize
@computer = DesktopComputer.new
end
def display=(display)
@computer.display = display
end
def add_cd(writable = false)
@computer.drives << Drive.new(:cd, 760, writable)
end
def add_dvd(writable = false)
@computer.drives << Drive.new(:dvd, 4700, writable)
end
def add_hard_disk(size_in_mb)
@computer.drives << Drive.new(:hard_disk, size_in_mb, true)
end
end
class LaptopBuilder < ComputerBuilder
def initialize
@computer = LaptopComputer.new
end
def display=(display)
raise "Laptop display must be lcd" unless display == :lcd
end
def add_cd(writer = false)
@computer.drives << LaptopDrive.new(:cd, 760, writer)
end
def add_dvd(writer = false)
@computer.drives << LaptopDrive.new(:dvd, 4000, writer)
end
def add_hard_disk(size_in_mb)
@computer.drives << LaptopDrive.new(:hard_disk, size_in_mb, true)
end
end
builder = LaptopBuilder.new
builder.add_cd_and_dvd_and_harddisk(false, false, 100000)
p builder.computer
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment