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.
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
Contextlớp này, lớp này biết trạng thái hiện tại là gì - Một
Statelớ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ừ
Statelớ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!