Design Pattern | State Pattern

Hãy suy nghĩ về cái gì bạn làm rất xen kẽ. Có thể bạn đang xem bài viết này, nhưng có lẽ bạn đang làm thêm điều gì khác nữa ? Bạn đang ngồi, đứng, hay nằm ? Giả sử tôi yêu cầu bạn thực hiện một điệu nhảy nhưng bạn vẫn đang ở trạng thái cũ, nếu bạn đang ngồi xuống, điệu nhảy của bạn có thể liên quan đến việc bạn vẫy tay vai và lắc đầu, nếu bạn đang đứng, bạn sẽ dùng thêm chân vào điệu nhảy của mình, nếu bạn đang nằm, bạn có thể giơ tay lên và ngọ nguậy cơ thể.

Tất cả những điều tôi bảo bạn phải làm là nhảy, và bạn đã chọn một điệu nhảy phù hợp với trạng thái của bạn, và tôi không phải xác định điệu nhảy của bạn sẽ trông như thế nào.

Vì các đối tượng trong code của bạn biết về trạng thái hiện tại của chúng, nó có thể chọn hành vi phù hợp dựa trên trạng thái của họ. Khi trạng thái của nó thay đổi, hành vi này có thể được thay đổi. Đây chính là State Pattern, mẫu trạng thái chủ yếu được sử dụng khi bạn cần thay đổi hành vi của một đối tượng dựa trên trạng thái mà nó đang hoạt động.

Hãy xem xét một ví dụ. Một máy bán hàng tự động thể hiện tốt State Pattern vì nó có một số trạng thái và hành động cụ thể dựa trên trạng thái đó. Giả sử tôi muốn mua một thanh Socola từ máy, thanh Socola có giá 1$, tôi nhét 1$ vào máy, máy sau đó phân phối thanh socola cho tôi. Đây sẽ là trường hợp điển hình của kịch bản này, nhưng hãy khám phá một số tình huống khác có thể xảy ra: Điều gì sẽ xảy ra nếu tôi đến máy bán hàng tự động, nhét $ vào và không muốn mua thanh Socola nữa ? Tôi sẽ nhấn nút đẩy tiền và máy sẽ trả lại tiền cho tôi. Trường hơp nữa là máy bán hàng tự động hết thanh Socola thì sao, máy bán hàng tự động cần theo dõi hàng tồn kho của nó và thông báo cho khách hàng khi không còn sản phẩm cụ thể nào nữa.

Trong sơ đồ UML được sử dụng như thế này:


Từ sơ đồ này, bạn có thể thấy rằng có ba trạng thái, Idle, Has One Dollar, và Out of Stock. Máy bạn hàng tự động ở một trong các trạng thái này tại từng thời điểm. Bạn cũng có thể thấy rằng có ba yếu tố kích hoạt, hoặc sự kiện: chèn dollar, khi đã chèn dollar, đẩy tiền ra, khi có yêu cầu rút tiền, khi có yêu cầu phân phối sản phẩm. Có hai hành động mà máy bán hàng tự động có thể làm, là doReturnMoney và doReleaseProduct. Code ví dụ sẽ như thế này:


Trước khi chúng ta tiếp cận máy bán hàng tự động, máy ở trạng thái Idle, không có gì xảy ra. Điều gì xảy ra khi chèn dollar vào ? Trạng thái của máy bán hàng tự động thay đổi.

Chúng ta hãy xem xét cách có thể biểu thị điều này trong Java, đầu tiên, chúng ta sẽ tạo ra singleton state object, chúng ta xác định ba state của đối tượng:


Lớp vendingMachine sẽ trông như thế này:


currentState đề cập đến một đối tượng trạng thái cụ thể, tùy theo trạng thái hiện tại của máy bán hàng tự động. Khi máy được khởi tạo với stock count lớn hơn 0, trạng thái hiện tại được đặt thành State.Idle, nếu số stock count không lớn hơn 0, trạng thái hiện tại sẽ là State.OutOfStock.


Bây giờ, hãy xem xét điều xảy ra khi chèn 1 dollar, bạn có thể thấy rằng nếu trạng thái hiện tại của máy là State.Idle thì trạng thái sẽ được đổi thành State.HasOneDollar. Nếu currentState của máy đã là State.HasOneDollar, tiền sẽ được trả lại và trạng thái sẽ lại trở thành State.Idle, nếu curentState là State.OutOfStock(), tiền sẽ được trả lại và trạng thái của máy vẫn là State.OutOfStock.

Nhưng những đối tượng này có thể khá lớn nhưng bản thân nó không có nhiều trách nhiệm, bây giờ chúng ta sẽ xem xét làm thế nào bạn có thể tái cơ cấu lại điều này bằng cách sử dụng Design Pattern.


Chúng ta sẽ xác định State Interface với phương thức cho mỗi kích hoạt mà trạng thái cần đáp ứng, đó là insertDollar(), ejectMoney(), dispnese(). Và chúng ta sẽ có các subclass implement để implement interface State.


Tiếp theo lớp IdleState sẽ trông như thế này, nó implement giao diện State, khi một dollar được chèn, phưng thức insertDolllar() được gọi, sau đó phương thức trạng thái được đặt trên đối tượng vendingMachine, điều này thay đổi trạng thái của máy thành HasOneDollarState.


Tương tự:


Nếu count !>1 (không lớn hơn 1) thì rơi vào trạng thái hết hàng.


Chương trình chính sẽ như thế này:


Chúc bạn thành công. Cảm ơn.




Nhận xét

Bài đăng phổ biến từ blog này

Hiểu về Norm Regularization

Những thuật toán nền tảng trong lĩnh vực Trí tuệ nhân tạo (Artificial Intelligence I)