`
jlaky
  • 浏览: 42907 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Design Patterns in Ruby [Digest 12] Builder

阅读更多

Imagine that you are create a computer machine, if you create a class named Computer

So the initializer will be such a painful and tedious parameter monster, you will find that it is a mess.

 

 

So the builder pattern make it much clear.

 

 

class ComputerBuilder
  attr_reader :computer
  def initialize
    @computer = Computer.new
  end
  def turbo(has_turbo_cpu=true)
    @computer.motherboard.cpu = TurboCPU.new
  end
  def display=(display)
    @computer.display=display
  end
  def memory_size=(size_in_mb)
    @computer.motherboard.memory_size = size_in_mb
  end
  def add_cd(writer=false)
    @computer.drives << Drive.new(:cd, 760, writer)
  end
  def add_dvd(writer=false)
    @computer.drives << Drive.new(:dvd, 4000, writer)
  end
  def add_hard_disk(size_in_mb)
    @computer.drives << Drive.new(:hard_disk, size_in_mb, true)
  end
end

 

 

builder = ComputerBuilder.new
builder.turbo
builder.add_cd(true)
builder.add_dvd
builder.add_hard_disk(100000)
computer = builder.computer

 

Builders not only ease the burden of creating complex objects, but also hide the implementation details.

 

We can create different kind of computer use polymorphic

 

 

class DesktopComputer < Computer
  # Lots of interesting desktop details omitted...
end

class LaptopComputer < Computer
  def initialize( motherboard=Motherboard.new, drives=[] )
    super(:lcd, motherboard, drives)
  end
  # Lots of interesting laptop details omitted...
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
end


class DesktopBuilder < ComputerBuilder
  def initialize
    @computer = DesktopComputer.new
  end
  def display=(display)
    @display = display
  end
  def add_cd(writer=false)
    @computer.drives << Drive.new(:cd, 760, writer)
  end
  def add_dvd(writer=false)
    @computer.drives << Drive.new(:dvd, 4000, writer)
  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

 

we can encapsulate the @computer with a method to validate the computer object:

 

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

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics