Created
May 28, 2013 23:24
-
-
Save ackintosh/5666911 to your computer and use it in GitHub Desktop.
Builder pattern in Ruby
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- 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