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

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值