Mẫu trạng thái
Thuộc phần Lập trình hướng đối tượng trong hành trình GDScript của Coddy. Bài học 54 trên 65.
Mẫu State cung cấp cho một đối tượng một đối tượng trạng thái riêng cho mỗi chế độ mà nó có thể ở trong đó. Đối tượng giao phần việc của mình cho trạng thái hiện tại, vì vậy hành vi của nó thay đổi khi trạng thái thay đổi.
Với một vài trạng thái, enum và match là đủ. Khi mỗi trạng thái phản ứng với nhiều hành động theo cách riêng, match sẽ dài thêm với mỗi trạng thái và mỗi hành động. Mẫu State chuyển các quy tắc của từng trạng thái vào lớp riêng:
# hero_state.gd
@abstract
class_name HeroState
extends RefCounted
@abstract func get_state_name() -> String
@abstract func handle(action: String) -> HeroStatehandle() trả về trạng thái tiếp theo: một đối tượng trạng thái mới để chuyển sang, hoặc self để giữ nguyên.
# idle_state.gd
class_name IdleState
extends HeroState
func get_state_name() -> String:
return "Idle"
func handle(action: String) -> HeroState:
if action == "run":
return RunState.new()
return selfRunState cũng được viết tương tự: tên của nó là "Running", và "stop" trả về IdleState.new(). Người hùng, tức ngữ cảnh, giữ trạng thái hiện tại và hỏi trạng thái đó cần làm gì:
# hero.gd
class_name Hero
extends RefCounted
var state: HeroState = IdleState.new()
func handle_action(action: String) -> void:
var next := state.handle(action)
if next != state:
print(state.get_state_name(), " -> ", next.get_state_name())
state = next# main.gd
var hero := Hero.new()
for action in ["stop", "run", "run", "stop"]:
hero.handle_action(action)Idle -> Running
Running -> IdleCùng một hành động có ý nghĩa khác nhau ở các trạng thái khác nhau: "stop" không làm gì khi đang ở trạng thái chờ và dừng anh hùng đang chạy. Mỗi quy tắc nằm trong lớp của trạng thái tương ứng, vì vậy một trạng thái mới như nhảy sẽ cần một lớp mới.
Các trạng thái trả về trạng thái tiếp theo thay vì lưu nhân vật chính. Nếu một trạng thái giữ nhân vật chính và nhân vật chính giữ trạng thái đó, sẽ tạo thành một vòng tham chiếu, khiến cả hai đối tượng không bao giờ được giải phóng.
Thử thách
DễCửa ở trạng thái Locked, Closed hoặc Open. DoorState (door_state.gd) khai báo get_state_name() và handle(action), còn LockedState (locked_state.gd) đã được viết: unlock đưa cửa về trạng thái Closed. Hãy viết:
ClosedState.handle():opentrả về mộtOpenStatemới,locktrả về mộtLockedStatemới, trường hợp khác trả vềself.OpenState.handle():closetrả về mộtClosedStatemới, trường hợp khác trả vềself.Door.handle_action(action): yêu cầu trạng thái hiện tại cho biết trạng thái tiếp theo. Nếu đó là cùng một đối tượng, hãy in raACTION: still STATE; nếu không, hãy in raACTION: OLD -> NEWrồi chuyển sang trạng thái mới.
Cửa bắt đầu ở trạng thái Locked. Code được cung cấp đọc số lượng hành động tiếp theo, rồi đọc từng hành động trên một dòng và in ra trạng thái cuối cùng. Với open, unlock, open, lock, đầu ra là:
open: still Locked
unlock: Locked -> Closed
open: Closed -> Open
lock: still Open
Final state: OpenCode của bạn nằm trong door.gd, closed_state.gd và open_state.gd. main.gd chứa code đầu vào/đầu ra được cung cấp và không thể chỉnh sửa.
Tự làm thử
extends Node
func _ready():
# Đoạn code đầu vào/đầu ra đã cho: giữ nguyên
var door := Door.new()
var count := int(OS.read_string_from_stdin())
for i in count:
door.handle_action(OS.read_string_from_stdin())
print("Final state: ", door.state.get_state_name())
Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Lập trình hướng đối tượng
1Nền tảng về OOP
Tệp bên ngoàiGiới thiệu về OOPLớp và đối tượngTừ khóa selfPhương thứcThuộc tínhHàm khởi tạo (_init)Ôn tập: máy tính đơn giản4Tính đa hình
Xem lại cách ghi đè phương thứcĐịnh kiểu vịtLớp và phương thức trừu tượngThiết kế interfaceÔn tập: máy tính hình học7Tín hiệu
Tín hiệu là gì?Khai báo và phát tín hiệuKết nối với tín hiệuTín hiệu có đối sốÔn tập: hệ thống sức khỏe10Các mẫu thiết kế phần 2
Mẫu lệnhMẫu bộ chuyển đổiMẫu trang tríMẫu phương thức khuôn mẫuMẫu trạng tháiMẫu tổng hợp2Thuộc tính của lớp
Biến instance và biến staticHàm staticPhương thức thiết lập thuộc tínhPhương thức lấy thuộc tínhQuy ước về tính riêng tưÔn tập: trình quản lý tài khoản ngân hàng5Tính đóng gói
Thành viên công khai và riêng tưXác thực bằng phương thức setterẨn thông tinThuộc tính chỉ đọcÔn tập: hệ thống hồ sơ học sinh8Khái niệm OOP nâng cao
Kết hợp và kế thừaLớp bên trongNode dưới dạng thành phầnRefCounted và NodeEnum trong lớpTự luyện tập: Trình biên dịch GDScript online