Decorator Pattern in Ruby
Bài đăng này đã không được cập nhật trong 6 năm
I. Problem
Chúng ta cần thay đổi trách nhiệm của một đối tượng, thêm một số tính năng. Giải pháp tôi muốn giới thiệu là Decorator.Decorator pattern là một mẫu thiết kế cho phép chúng ta thêm hành vi vào đối tượng mà không ảnh hưởng đến các đối tượng khác của cùng một lớp. Decorator Pattern là một lựa chọn hữu ích để tạo các lớp con.
II. Solution
Trong Decorator pattern chúng ta tạo ra một đối tượng mà bao bọc một đối tượng khác để thực hiện hành động trên cùng một giao diện, giống như cấc phương thức chuyển tiếp. Tuy nhiên, trước khi ủy quyền cho đối tượng thực, nó thực hiện tính năng bổ sung trước. Vì tất cả các Decorator đều triển khai cùng một inteface cốt lõi, chúng ta có thể xây dựng các chuỗi các decorator và tập hợp chúng lại để kết hợp các tính năng khi runtime.
III. Example
Dưới đây là việc thực hiện của một đối tượng mà chỉ cần viết một dòng text vào một file:
class SimpleWriter
def initialize(path)
@file = File.open(path, 'w')
end
def write_line(line)
@file.print(line)
@file.print("\n")
end
def pos
@file.pos
end
def rewind
@file.rewind
end
def close
@file.close
end
end
Một lúc nào đó, chúng ta có thể cần in số dòng trước mỗi dòng hoặc thời gian hoặc tổng số ký tự.Chúng ta có thể đạt được điều này bằng cách thêm các phương thức mới vào Class thực hiện chính xác những gì chúng ta muốn, hoặc bằng cách tạo một subclass mới cho mỗi trường hợp sử dụng.Tuy nhiên, không có giải pháp nào trong số này là tối ưu.Trong trường hợp thứ nhất, khách hàng nên biết loại line nào sẽ được print ra mọi lúc.Với trường hợp sau, chúng ta có thể cần có một số lượng lớn các lớp con, đặc biệt nếu chúng ta muốn kết hợp các tính năng mới thì việc quản lý các class sẽ trở nên phức tạp.Vì vậy, hãy tạo một lớp Decorator dựa trên cơ sở thực hiện cùng một interface mà class Writer của chúng ta và các delegate trên nó:
class WriterDecorator
def initialize(real_writer)
@real_writer = real_writer
end
def write_line(line)
@real_writer.write_line(line)
end
def pos
@real_writer.pos
end
def rewind
@real_writer.rewind
end
def close
@real_writer.close
end
end
Bây giờ, bằng cách extending class WriteDecorator, chúng ta có thể thêm các tính năng bổ sung ở trên cùng của basic writer, chẳng hạn như thêm đánh số dòng:
class NumberingWriter < WriterDecorator
def initialize(real_writer)
super(real_writer)
@line_number = 1
end
def write_line(line)
@real_writer.write_line("#{@line_number}: #{line}")
@line_number += 1
end
end
writer = NumberingWriter.new(SimpleWriter.new('final.txt'))
writer.write_line('Hello out there')
Nếu chúng ta tạo ra các decorator mà thực hiện cùng một interface cốt lõi, chúng ta có thể xâu chuỗi chúng lại:
class TimeStampingWriter < WriterDecorator
def write_line(line)
@real_writer.write_line("#{Time.new}: #{line}")
end
end
writer = CheckSummingWriter.new(TimeStampingWriter.new(
NumberingWriter.new(SimpleWriter.new('final.txt'))))
writer.write_line('Hello out there')
IV. Tham khảo
All rights reserved