Design Pattern - Factory Method
Để hiểu hơn về factory, hãy cùng bắt đầu với một vấn đề trong lập trình. Hãy tưởng tượng bạn được yêu cầu build một mô hình cuộc sống trong một cái ao, với những chú vịt. Bạn sẽ làm thế nào ? Đầu tiên hãy xây dựng class cho chú vịt Duck class Duck def initialize ( name ) @name ...
Để hiểu hơn về factory, hãy cùng bắt đầu với một vấn đề trong lập trình. Hãy tưởng tượng bạn được yêu cầu build một mô hình cuộc sống trong một cái ao, với những chú vịt. Bạn sẽ làm thế nào ?
Đầu tiên hãy xây dựng class cho chú vịt Duck
class Duck def initialize(name) @name = name end def eat puts("Duck #{@name} is eating.") end def speak puts("Duck #{@name} says Quack!") end def sleep puts("Duck #{@name} sleeps quietly.") end end
Tiếp theo là cái ao Pond với nhiều vịt Duck:
class Pond def initialize(number_ducks) @ducks = [] number_ducks.times do |i| duck = Duck.new("Duck#{i}") @ducks << duck end end def simulate_one_day @ducks.each {|duck| duck.speak} @ducks.each {|duck| duck.eat} @ducks.each {|duck| duck.sleep} end end
Nếu giờ chúng ta có thêm yêu cầu xây dựng thêm object con ếch Frog ở vũng nước Puddle thì phải làm sao ? Sẽ rất dễ để tạo 1 class Frog vì nó khá giống với interface của con vịt Duck.
class Frog def initialize(name) @name = name end def eat puts("Frog #{@name} is eating.") end def speak puts("Frog #{@name} says Crooooaaaak!") end def sleep puts("Frog #{@name} doesn't sleep; he croaks all night!") end end
Nhưng với class Pond thì hiện chúng ta đang implement chỉ khởi tạo cho Duck. Nếu muốn thêm Frog thì cần tách riêng các sinh vật sống trong ao, cụ thể là Duck hoặc Frog. Nếu bạn bằng cách nào đó có thể khiến class Pond hỗ trợ cả Duck và Frog thì cũng rất khó nếu muốn gọi ra các method của từng object vì chúng ta không thể biết chúng ta đang gọi object thuộc class nào.
Có một cách để giải quyết vấn đề chọn class phù hợp đó là tách thành các subclass thông qua một base class.
class Pond def initialize(number_animals) @animals = [] number_animals.times do |i| animal = new_animal("Animal#{i}") @animals << animal end end def simulate_one_day @animals.each {|animal| animal.speak} @animals.each {|animal| animal.eat} @animals.each {|animal| animal.sleep} end end
Chúng ta cần build 2 subclass của Pond, một cho Duck và một cho loại khác (Frog).
class DuckPond < Pond def new_animal(name) Duck.new(name) end end class FrogPond < Pond def new_animal(name) Frog.new(name) end end
GoF gọi kỹ thuật giải quyết việc chọn class bằng cách chia thành các subclass là Factory Method pattern.
UML diagram của pattern này như sau:
Trong ví dụ phía trên thì:
- Creator chính là Pond class
- Hai loại pond (DuckPond, FrogPond) chính là ConcreteCreator
- Và 2 products là Duck class và Frog class.
Kết luận
Factory Method pattern là một trong những design pattern được sử dụng phổ biến, nó cung cấp một trong những cách tốt nhất để tạo ra một object.
Trong Factory Method pattern, chúng ta tạo ra object mà không lộ logic với client mà tham chiếu tới một đối tượng mới sử dụng một common interface.
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