+1

Design Pattern - Builder

Builder pattern là gì?

Với Factory Pattern, chúng ta có thể dễ dàng tạo ra đúng object cần thiết. Tuy nhiên việc tạo đúng đối tượng chưa hẳn đã là vấn đề chính khi thiết kế phần mềm. Vấn đề chính đôi khi là làm thế nào để lắp ráp các object đó lại với nhau. Công việc lắp ráp, cấu hình các object phức tạp sẽ dễ dàng hơn nếu chúng ta hiểu về Builder Pattern.

Ví dụ

Hãy thử tưởng tượng, chúng ta đang viết một hệ thống hỗ trợ cho một nhà máy sản xuất computer nhỏ. Mỗi máy tính sẽ được tùy chỉnh theo đơn đặt hàng vì thế ta cần theo dõi các thành phần cho mỗi máy. Ở đây, ta có thể giả sử mỗi máy tính sẽ gồm một màn hình (display), một motherboard và một số driver:

class Computer
  attr_accessor :display
  attr_accessor :motherboard
  attr_reader :drives

  def initialize(display=:crt, motherboard=Motherboard.new, drives=[])
    @motherboard = motherboard
    @drives = drives
    @display = display
  end
end

display có thể là loại :crt hoặc :lcd motherboard là 1 object, nó có một bộ nhớ memory nhất định với một CPU hoặc TurboCPU

class CPU
  # Common CPU stuff...
end

class BasicCPU < CPU
  # Lots of not very fast CPU-related stuff...
end

class TurboCPU < CPU
  # Lots of very fast CPU stuff...
end

class Motherboard
  attr_accessor :cpu
  attr_accessor :memory_size

  def initialize(cpu=BasicCPU.new, memory_size=1000)
    @cpu = cpu
    @memory_size = memory_size
  end
end

drivers có 3 loại: hard drive, CD, và DVD

class Drive
  attr_reader :type # either :hard_disk, :cd or :dvd
  attr_reader :size # in MB
  attr_reader :writable # true if this drive is writable

  def initialize(type, size, writable)
    @type = type
    @size = size
    @writable = writable
  end
end

Với những model đơn giản, chúng ta có thể xây dựng một Computer cơ bản:

# Build a fast computer with lots of memory...
motherboard = Motherboard.new(TurboCPU.new, 4000)
# ...and a hard drive, a CD writer, and a DVD
drives = []
drives << Drive.new(:hard_drive, 200000, true)
drives << Drive.new(:cd, 760, true)
drives << Drive.new(:dvd, 4700, false)
computer = Computer.new(:lcd, motherboard, drives)

Xây dựng một Builder như thế nào ?

Tư tưởng của Builder khá đơn giản, đó là đưa tất cả logic và đóng gói chúng vào một Class của riêng nó. Builder class phụ trách lắp ráp các thành phần của một object phức tạp. Mỗi một builder là một interface cho phép bạn chỉ định cấu hình của từng đối tượng theo từng bước.

builder.PNG

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

Các bước cấu hình một computer:

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

computer = builder.computer

Ý nghĩa của Builder

Builder không chỉ giảm bớt gánh nặng khi phải xây dựng một object phức tạp mà còn ẩn đi những chi tiết cài đặt một cách hoàn hảo.

Các director không cần phải biết cụ thể về các thành phần tạo nên các object mới. Như khi ta sử dụng ComputerBuilder ta không cần biết về các Class DVD hay hard disk, ta chỉ cần yêu cầu cấu hình máy tính mình cần.

Tham khảo

Github (updating):https://github.com/ducnhat1989/design-patterns-in-ruby

Sách: “DESIGN PATTERNS IN RUBY” của tác giả Russ Olsen

Bài viết liên quan:


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí