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 ...
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.
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
:
- CÁC NGUYÊN TẮC TRONG DESIGN PATTERN