Hãy viết một bài luận dài vô tận ! Nhưng đó là một nhiệm vụ bất khả thi. Tuy nhiên, chúng ta có thể tạo một quy trình mà nếu chạy mãi mãi sẽ tạo ra một bài luận dài vô tận. Đủ gần .
Bây giờ, rõ ràng bạn có thể tạo một bài luận dài và lặp đi lặp lại chỉ bằng một dòng mã Python:
>>> "This is water. " * 20 'This is water. This is water. This is water. This is water. This is water. This is water. This is water. This is water. This is water. This is water. This is water. This is water. This is water. This is water. This is water. This is water. This is water. This is water. This is water. This is water. '
Yaawn … la ó! Thay vào đó, chúng ta sẽ tạo ra một bài luận thú vị hơn nhiều bằng cách sử dụng mẫu thiết kế State trong bài viết này.
Đầu tiên, chúng ta sẽ hiểu máy trạng thái là gì và chúng liên quan như thế nào đến mẫu thiết kế Trạng thái. Tiếp theo, chúng ta sẽ tạo một cỗ máy trạng thái có thể tạo ra một bài luận vô tận và thú vị (hợp lý). Sau đó, chúng ta sẽ xem xét ngắn gọn về mẫu thiết kế trạng thái. Cuối cùng, chúng ta sẽ dịch máy trạng thái đó thành mã hướng đối tượng bằng cách sử dụng mẫu thiết kế trạng thái.
Các mẫu thiết kế phần mềm là những cách hiệu quả để giải quyết các vấn đề thường xảy ra. Khi được áp dụng phù hợp, các mẫu thiết kế phần mềm như mẫu trạng thái có thể giúp bạn viết phần mềm có khả năng mở rộng, bảo trì và kiểm thử tốt hơn.
Về bản chất, mẫu thiết kế Trạng thái chuyển Máy trạng thái thành mã hướng đối tượng.
Nếu bạn không quen với máy trạng thái thì đó là một khái niệm khá đơn giản. Một máy trạng thái có các trạng thái và chuyển tiếp . Các trạng thái là những thuộc tính nhất định trong hệ thống mà chúng ta quan tâm và việc chuyển đổi trạng thái là những hành động làm thay đổi những thuộc tính này và do đó cũng gây ra sự thay đổi trạng thái.
Vì tôi có nền tảng về Robot học (trong số những thứ khác) và vì máy trạng thái được sử dụng rộng rãi trong Robotics nên tôi sẽ sử dụng một ví dụ đơn giản về máy hút bụi robot để minh họa cách hoạt động của máy trạng thái.
Sơ đồ máy trạng thái vẽ nên một bức tranh trực quan về cách robot hoạt động, ngay cả khi bạn chưa từng gặp phải máy trạng thái. Chúng ta hãy đi qua hoạt động này từng bước một.
Do đó, máy hút bụi rô-bốt của chúng tôi có ba trạng thái — Đã gắn , Đang làm sạch và Đang sạc — và có các chuyển đổi dựa trên khả năng phát hiện cảm giác của sàn nhà và pin của sàn.
Bây giờ chúng ta đã hiểu về máy trạng thái ở mức cơ bản, hãy tạo một máy trạng thái có khả năng viết một bài luận vô hạn.
Trên đây là một máy trạng thái sử dụng ngữ pháp tiếng Anh để tạo ra một bài luận gồm các câu ngắn, đơn giản. Tôi hứa rằng chúng ta sẽ sớm có phiên bản thú vị hơn, nhưng đây sẽ là điểm khởi đầu tốt để hiểu biết. Chúng ta hãy xem xét nó hoạt động như thế nào.
Máy trạng thái này có thể tạo ra một bài luận (vô nghĩa) trông như thế này.
Thế giới sủa màu đỏ! Anh họ Harry mưa hôi? Những chú hổ lung linh vui vẻ. …
Mặc dù “không xác định” nghe có vẻ phức tạp nhưng với mục đích của chúng tôi, nó chỉ có nghĩa là thêm vào một số tính ngẫu nhiên. Về cơ bản, chúng tôi đang thêm một kiểu tung đồng xu trước khi chuyển sang một số tiểu bang. Bạn sẽ hiểu ý tôi là gì.
Máy trạng thái không xác định ở trên rất giống với máy trước đó. Sự khác biệt duy nhất là:
Với việc giới thiệu tính ngẫu nhiên, phủ định và liên từ, giờ đây chúng ta có thể tạo ra các câu có độ dài thay đổi và thú vị hơn.
Bây giờ, hãy hiểu cách hoạt động của mẫu thiết kế trạng thái. Một lần nữa, hãy nhớ rằng chúng ta đang cố gắng chuyển một máy trạng thái sang mã hướng đối tượng.
Trong máy trạng thái tạo bài luận, hãy quan sát rằng mọi trạng thái đều cần thực hiện hai việc.
Từ quan điểm của một quốc gia cụ thể, không có gì khác mà nó cần biết hoặc làm. Thay vì bị sa lầy bởi sự phức tạp của toàn bộ hệ thống - tất cả các trạng thái và chuyển đổi của nó - chúng ta chỉ có thể tập trung vào một trạng thái tại một thời điểm. Theo quan điểm của tôi, kiểu cô lập và tách rời này là điểm hấp dẫn nhất của mô hình Bang.
Dưới đây, chúng ta có sơ đồ UML cho mẫu thiết kế Trạng thái. Có một số bối cảnh trong đó mỗi trạng thái hoạt động, được minh họa bởi lớp Context
. Đối tượng bối cảnh có một thuộc tính trạng thái riêng, nó sử dụng để gọi trạng thái hiện tại để thực hiện hành động của nó. Mỗi trạng thái triển khai một giao diện State
với các phương thức để thực hiện hành động hoặc thao tác của nó và trả về trạng thái tiếp theo.
Nếu chúng ta ánh xạ điều này vào ví dụ tạo bài luận, sơ đồ UML sẽ trông như thế này.
WordState
bây giờ là một lớp trừu tượng (được biểu thị bằng chữ in nghiêng) thay vì một giao diện. Các lớp trừu tượng có thể có một số phương thức và thuộc tính trừu tượng (không được triển khai), trong khi các lớp khác có thể được định nghĩa. Các giao diện hoàn toàn trừu tượng: tất cả các phương thức của chúng đều trừu tượng. Tôi đã thực hiện thay đổi này vì việc triển khai generateWord
giống nhau ở tất cả các trạng thái và việc tránh mã trùng lặp là điều tốt.
Hãy chia nhỏ từng thuộc tính và phương thức ở trên. Trong lớp EssayContext
, chúng ta có:
state
: Tham chiếu đến đối tượng WordState
hiện tại.essayBody
: Danh sách tất cả các từ được tạo cho đến nay.setState()
: Setter để thay đổi thuộc tính state
.addWord()
: Phương thức thêm từ tiếp theo vào nội dung bài viết.generateEssay()
: Chúng tôi gọi phương thức này để tạo bài luận của mình; chúng tôi dừng lại khi essayBody
có chiều dài lớn hơn length
.printEssay()
: Trả về một chuỗi bài luận được tạo.
Trong lớp trừu tượng WordState
, chúng ta có:
wordList
: Thuộc tính trừu tượng (được biểu thị bằng chữ in nghiêng) cho danh sách các từ mà chúng tôi chọn từ để tạo.generateWord()
: Phương thức thêm từ được tạo vào ngữ cảnh bài luận.nextState()
: Phương thức trừu tượng để trả về trạng thái tiếp theo.
Chúng tôi sẽ sử dụng NounState
làm ví dụ đại diện cho tất cả các trạng thái cụ thể khác được kế thừa từ WordState
.
wordList
: Danh sách các danh từ mà chúng ta chọn từ để tạo.nextState()
: Trả về trạng thái tiếp theo.
Bây giờ, chúng ta đã có mọi thứ cần thiết để thực sự triển khai điều này trong mã. Hãy tiếp tục và làm điều đó!
Trước tiên chúng ta hãy viết lớp EssayContext
trong một tệp có tên là essay_context.py
. Chúng ta sẽ bỏ trường hợp lạc đà và chuyển sang trường hợp rắn bởi vì Python là một... con rắn (xin lỗi).
from word_state import WordState class EssayContext: def __init__(self, state: WordState): self.state = state self.essay_body: list[str] = [] def set_state(self, state: WordState): self.state = state def add_word(self, word: str): self.essay_body.append(word) def generate_essay(self, length: int): while len(self.essay_body) < length: self.state.generate_word(self) def print_essay(self) -> str: return " ".join(self.essay_body)
Sau đó, hãy thêm các trạng thái vào một tệp có tên word_state.py
.
import abc import numpy as np class WordState(abc.ABC): word_list: list[str] @classmethod def generate_word(cls, context: "EssayContext"): word = np.random.choice(cls.word_list) context.add_word(word) context.set_state(cls.next_state()) @classmethod @abc.abstractmethod def next_state(cls) -> "WordState": pass class NounState(WordState): word_list: list[str] = ["everything", "nothing"] @classmethod def next_state(cls): return VerbState class VerbState(WordState): word_list: list[str] = ["is", "was", "will be"] @classmethod def next_state(cls): heads = np.random.rand() < 0.5 if heads: return NegationState return AdjectiveState class NegationState(WordState): word_list: list[str] = ["not"] @classmethod def next_state(cls): return AdjectiveState class AdjectiveState(WordState): word_list: list[str] = ["fantastic", "terrible"] @classmethod def next_state(cls): heads = np.random.rand() < 0.5 if heads: return ConjunctionState return EndmarkState class ConjunctionState(WordState): word_list: list[str] = ["and", "but"] @classmethod def next_state(cls): return NounState class EndmarkState(WordState): word_list: list[str] = [".", "!"] @classmethod def next_state(cls): return NounState
Cuối cùng, hãy thêm mã để chạy mọi thứ trong main.py
.
from essay_context import EssayContext from word_state import NounState if __name__ == '__main__': ctx = EssayContext(NounState) ctx.generate_essay(100) print(ctx.print_essay())
Chạy python main.py
cho chúng ta kết quả đầu ra sau (mỗi lần khác nhau do tính không xác định):
'everything is not terrible and nothing was terrible ! everything will be not fantastic but everything is fantastic . everything will be fantastic . nothing will be fantastic and nothing will be terrible ! everything was not fantastic and everything will be not terrible . everything was terrible . nothing was terrible but nothing will be fantastic ! nothing is not terrible . nothing was not fantastic but everything was not fantastic ! everything will be not fantastic but everything will be terrible ! everything will be not fantastic . everything is fantastic but nothing will be not terrible ! everything will be not fantastic but nothing was not fantastic !'
Không tệ cho một hệ thống đơn giản như vậy! Chúng ta cũng có thể mở rộng các danh sách từ khác nhau hoặc thêm nhiều trạng thái hơn để làm cho việc tạo bài luận trở nên phức tạp hơn. Chúng tôi thậm chí có thể giới thiệu một số API LLM để đưa bài luận của mình lên một tầm cao mới.
Máy trạng thái và mẫu Trạng thái rất phù hợp để mô hình hóa và tạo ra các hệ thống có khái niệm được xác định rõ ràng về “trạng thái”. Nghĩa là, có những hành vi và thuộc tính cụ thể gắn liền với từng trạng thái. Robot hút bụi đang làm sạch, được gắn đế hoặc đang sạc. TV của bạn có thể BẬT hoặc TẮT và các nút trên điều khiển từ xa của TV sẽ hoạt động khác nhau tùy theo trạng thái của TV.
Nó cũng phù hợp để tạo hoặc xác định các chuỗi có mẫu được xác định rõ. Điều này áp dụng cho ví dụ tạo bài luận của chúng tôi.
Cuối cùng, bạn có thể hỏi, “Tất cả những điều này có ý nghĩa gì?” Tại sao chúng ta lại phải tốn nhiều công sức để xác định các trạng thái và giai cấp khác nhau để tạo ra bài luận “vô hạn” này? Chúng ta có thể viết 20 (hoặc ít hơn) dòng mã Python để đạt được hành vi tương tự.
Câu trả lời ngắn gọn là để có khả năng mở rộng tốt hơn.
Hãy tưởng tượng nếu thay vì chỉ ba hoặc năm tiểu bang, chúng ta có 50 hoặc 500 tiểu bang. Đây không phải là cường điệu; hệ thống doanh nghiệp thực sự có mức độ phức tạp đó. Đột nhiên, mẫu Trạng thái có vẻ hấp dẫn hơn nhiều vì tính tách rời và cô lập của nó. Chúng ta chỉ có thể tập trung vào một trạng thái tại một thời điểm mà không cần phải ghi nhớ toàn bộ hệ thống trong đầu. Việc đưa ra các thay đổi sẽ dễ dàng hơn vì một trạng thái sẽ không ảnh hưởng đến các trạng thái khác. Nó cũng cho phép kiểm tra đơn vị dễ dàng hơn, một phần quan trọng của hệ thống có thể mở rộng và bảo trì.
Cuối cùng, mô hình Bang không chỉ là quản lý các bang; giống như tất cả các mẫu thiết kế, nó là một kế hoạch chi tiết để xây dựng các hệ thống có khả năng mở rộng và bảo trì cũng như độ phức tạp của chúng.