Computer >> Máy Tính >  >> Lập trình >> Ruby

Cách sử dụng Gem AASM để tạo máy trạng thái trong Ruby

Hôm nay, bạn sẽ tìm hiểu về các máy trạng thái, cách chúng hoạt động và cách sử dụng chúng trong các dự án Ruby của bạn với AASM gem.

Bây giờ :

Hãy tưởng tượng đèn giao thông…

Nó có thể có màu đỏ, xanh lá cây hoặc vàng.

Khi nó thay đổi màu sắc, tiếp theo màu dựa trên hiện tại một.

Cách sử dụng Gem AASM để tạo máy trạng thái trong Ruby

Giả sử rằng đây là loại hình tạo ra tiếng vang cho người mù để họ biết khi nào họ có thể vượt qua.

Bây giờ :

Bạn đang viết phần mềm cho thứ này.

Làm thế nào để bạn biết âm thanh nào sẽ phát mỗi lần và màu gì sẽ tiếp theo?

Bạn có thể viết một số câu lệnh if như sau:

if @light.state == "green"
  @light.play_green_sound
end

if @light.state == "green"
  @light.change_to_yellow
end

# ...

Mã kiểm tra trạng thái này sẽ ở khắp nơi!

Chúng tôi có thể cải thiện điều này bằng cách nào?

Nếu bạn áp dụng các nguyên tắc Thiết kế hướng đối tượng, bạn sẽ khám phá lại Mẫu thiết kế trạng thái.

Mẫu thiết kế trạng thái là gì?

State Design Pattern là một cách để triển khai máy trạng thái.

Bạn sẽ cần 3 thành phần :

  • Một Context lớp này, lớp này biết trạng thái hiện tại là gì
  • Một State lớp, lớp này xác định các phương thức sẽ được triển khai bởi các trạng thái riêng lẻ
  • Một lớp cho mọi tiểu bang. Các lớp này sẽ kế thừa từ State lớp học

Trong ví dụ về đèn giao thông của chúng tôi, ngữ cảnh là TrafficLight chính nó.

Và các trạng thái là Green , Red &Yellow .

Mọi tiểu bang sẽ biết phải làm gì.

Lợi ích lớn ?

Mọi trạng thái đều tự biết nên không cần kiểm tra trạng thái hiện tại. Điều này chuyển thành các câu lệnh ít điều kiện hơn, thường là một nguồn phức tạp.

Triển khai đèn giao thông

Hãy xem mã để triển khai thực tế mẫu này.

Đây là TrafficLight :

class TrafficLight
  def initialize
    @state = nil
  end

  def next_state(klass = Green)
    @state = klass.new(self)

    @state.beep
    @state.start_timer
  end
end

Đây là State cơ sở :

class State
  def initialize(light)
    @light = light
  end

  def beep
  end

  def next_state
  end

  def start_timer
  end
end

Có, 3 phương thức này trống.

Đó là quy ước chung trong các ngôn ngữ lập trình khác (như Java) để xác định “giao diện” này, nhưng nó không phổ biến trong Ruby.

Đây là đây cho mục đích trình diễn.

Tuy nhiên, chúng tôi vẫn muốn chia sẻ initialize giữa tất cả các trạng thái vì tất cả chúng đều cần ngữ cảnh (TrafficLight đối tượng) để báo hiệu thay đổi trạng thái .

Bây giờ :

3 trạng thái trông rất giống nhau, vì vậy tôi sẽ chỉ cho bạn mã của một trong số chúng.

Đây là Green trạng thái:

class Green < State
  def beep
    puts "Color is now green"
  end

  def next_state
    @light.next_state(Yellow)
  end

  def start_timer
    sleep 5; next_state
  end
end

Mọi trạng thái đều biết cách thức và thời điểm chuyển sang trạng thái tiếp theo.

Ví dụ về trò chơi AI

Bạn có thể sử dụng máy trạng thái để giải quyết các trò chơi phụ thuộc vào trạng thái hiện tại, chẳng hạn như RubyWarrior.

Trong RubyWarrior, bạn được cung cấp một đối tượng người chơi và một bảng.

Mục tiêu là :

  • Đánh bại tất cả kẻ thù trên bàn cờ
  • Tiếp cận lối ra trong khi giữ HP của bạn trên 0

Bạn có thể thực hiện từng bước một và bạn phải lựa chọn tốt nếu muốn hoàn thành cấp độ.

Xem xét trạng thái hiện tại sẽ giúp bạn đưa ra lựa chọn đó.

Đó là lý do tại sao máy trạng thái là một giải pháp tốt.

Đây là một ví dụ :

class Attacking < State
  def play(warrior)
    warrior.attack!

    @player.set_state(Healing) unless enemy_found?(warrior)
  end
end

Đây là một trong những trạng thái mà chiến binh của chúng ta có thể ở, khi chúng ta không có bất kỳ kẻ thù nào trong tầm mắt, chúng ta chuyển sang Healing trạng thái phục hồi sau thiệt hại trong trận chiến.

Sử dụng Đá quý AASM

Nếu bạn muốn theo dõi trạng thái hiện tại trong khi đảm bảo rằng quá trình chuyển đổi là hợp lệ thì bạn có thể sử dụng đá quý máy trạng thái như AASM.

Đá quý này được xây dựng dựa trên ý tưởng về sự kiện (như nhấn công tắc đèn) để kích hoạt chuyển đổi sang các trạng thái khác.

Đây là một ví dụ :

require 'aasm'

class Light
  include AASM

  aasm do
    state :on, :off

    event :switch do
      transitions :from => :on, :to => :off, :if => :on?
      transitions :from => :off, :to => :on, :if => :off?
    end
  end
end

Cách sử dụng lớp này :

light = Light.new

p light.on?
# true

light.switch

p light.on?
# false

Sử dụng máy trạng thái này, bạn chỉ có thể chuyển sang trạng thái "bật" nếu trạng thái hiện tại là "tắt". Bạn cũng có thể có một số lệnh gọi lại (trước / sau) để chạy mã cụ thể trong quá trình chuyển đổi trạng thái.

Các lệnh gọi lại này có thể bao gồm những thứ như:

  • Gửi email
  • Ghi nhật ký thay đổi trạng thái
  • Cập nhật trang tổng quan giám sát trực tiếp

Ngoài ra, AASM có tùy chọn để lưu trạng thái hiện tại vào cơ sở dữ liệu bằng cách sử dụng ActiveRecord .

AASM Gem Video

Tóm tắt

Bạn đã học về máy trạng thái, mô hình thiết kế trạng thái và đá quý AASM! Hãy tiếp tục tìm hiểu ngay bây giờ bằng cách đăng ký nhận bản tin Ruby của tôi (hơn 7000 người đăng ký) để bạn không bỏ lỡ các bài viết mới và mẹo Ruby dành riêng cho người đăng ký .

Bây giờ là lúc thực hành với những ý tưởng mới này 🙂

Cảm ơn vì đã đọc!