Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Ruby

Thành thạo mẫu Singleton trong Ruby – Hướng dẫn thực hành & Tại sao nên tránh nó

Bạn có bao giờ muốn tạo một class chỉ có thể có một instance?

Có? Không? Có lẽ?

Vâng…

Đó chính xác là mẫu Singleton.

Không có vấn đề gì với điều đó.

Nhưng một số người gọi đây là anti-pattern vì nó có thể được dùng làm cái cớ cho thiết kế kém.

Hãy xem ví dụ mã để bạn học cách nó hoạt động.

Ví dụ mã Mẫu Singleton

Ý tưởng của mẫu Singleton là bạn muốn một class chỉ có một instance.

Cách làm:

  • Bạn làm phương thức new trở thành private
  • Bạn định nghĩa một phương thức class tên instance trả về instance duy nhất cho class đó

Vì đây là một mẫu thiết kế phổ biến, thư viện chuẩn Ruby đi kèm với module Singleton bạn có thể include vào bất kỳ class nào.

Nó trông như sau:

require 'singleton'
class Shop
  include Singleton
end

Bây giờ nếu bạn cố tạo đối tượng Shop với Shop.new bạn sẽ thấy:

Shop.new # NoMethodError: private method `new' called for Shop:Class

Và nếu bạn muốn lấy đối tượng Shop duy nhất bạn có thể dùng phương thức instance:

Shop.instance.object_id # 5659218
Shop.instance.object_id # 5659218

Bạn có thể thấy nó luôn là cùng một đối tượng vì object_id không bao giờ thay đổi.

Điều bạn cần nhớ:

Đây là một mẫu đơn giản, nó giới hạn việc tạo đối tượng ở 1 đối tượng & bạn có thể yêu cầu đối tượng đó bất cứ khi nào muốn.

Tại sao Bạn KHÔNG nên dùng Mẫu này

Mẫu Singleton thường là cái cớ để có某种形式 của biến toàn cục (global variable) & chúng ta biết biến toàn cục là xấu vì bạn không có sự kiểm soát đối với chúng. Điều này làm cho việc kiểm thử khó khăn hơn & có thể tăng coupling.

“Vấn đề thực sự với Singleton là chúng cho bạn một cái cớ tốt để không suy nghĩ kỹ lưỡng về độ hiển thị phù hợp của một đối tượng.” — Kent Beck

Hãy tưởng tượng có một đối tượng mà hầu hết các class của bạn phụ thuộc vào, đó là thứ mẫu Singleton có thể trở thành. Chúc may mắn khi refactor cái đó!

Bây giờ:

Có trường hợp nào tốt để dùng mẫu này không?

Tìm kiếm trên Github thấy một số repo sử dụng mẫu Singleton kết hợp với mẫu Null Object.

Tôi đoán điều đó hợp lý, Rails sử dụng điều này như một phần của ActionPack.

Đây là mã:

class AllType < Type
  include Singleton
  def initialize
    super "*/*", :all
  end
  def all?; true; end
  def html?; true; end
end

Đây là class kế thừa từ Type.

Khi bạn tạo đối tượng AllType qua phương thức instance, nó sẽ gọi super & trả về đối tượng.

Mỗi lần bạn gọi instance sau đó bạn sẽ nhận được cùng một đối tượng.

Kết luận:

Có, mẫu này có thể hữu ích trong đúng tình huống, nhưng bạn không muốn dùng nó mà không suy nghĩ kỹ.

Video

Tóm tắt

Bạn đã học về mẫu thiết kế singleton, cách triển khai nó trong Ruby & tại sao bạn nên tránh nó hầu hết thời gian.

Bạn nghĩ sao về mẫu này? Bạn đã thấy nó trước đây? Cho tôi biết trong bình luận 🙂

Cảm ơn bạn đã đọc!