
Chào các "dev" tương lai của Gen Z! Anh là Creyt đây, hôm nay chúng ta sẽ cùng "mổ xẻ" một khái niệm nghe tưởng chừng đơn giản mà lại cực kỳ quan trọng trong lập trình hướng đối tượng (OOP) nói chung và Java nói riêng: State.
1. State là gì? Để làm gì? (Góc nhìn Gen Z)
Nói một cách dễ hiểu nhất, State của một đối tượng trong Java OOP giống như "tâm trạng" hay "tình hình hiện tại" của nó vậy. Cứ hình dung thế này: bạn đang lướt TikTok của crush đúng không? Profile của crush có thể đang ở trạng thái "Độc thân", "Đang hẹn hò", hoặc "Đã kết hôn" (mong là không phải cái cuối). Hoặc đơn giản hơn, cái đèn trong phòng bạn có thể đang ở trạng thái "Bật" hoặc "Tắt".
Trong lập trình, State của một đối tượng chính là tổng hòa của tất cả các giá trị thuộc tính (fields) của đối tượng đó tại một thời điểm nhất định. Nó cho chúng ta biết đối tượng đang như thế nào.
Để làm gì ư? Đơn giản thôi! Các đối tượng hành xử khác nhau tùy thuộc vào trạng thái của chúng. Một tài khoản TikTok "Độc thân" có thể nhận được nhiều tin nhắn làm quen hơn tài khoản "Đang hẹn hò". Một cái đèn "Bật" sẽ chiếu sáng, còn cái đèn "Tắt" thì không. State là cốt lõi để đối tượng có thể tương tác, thay đổi và thể hiện hành vi một cách có ý nghĩa trong chương trình của bạn.
2. Code Ví Dụ Minh Họa: Công Tắc Điện "Thông Minh" (mà không thông minh lắm)
Để dễ hình dung, chúng ta hãy xây dựng một đối tượng LightSwitch (công tắc đèn) đơn giản. Nó chỉ có một trạng thái duy nhất: isOn (đang bật hay tắt).
class LightSwitch {
private boolean isOn; // <-- Đây chính là "state" của cái công tắc này
// Constructor: Khởi tạo công tắc, mặc định là TẮT
public LightSwitch() {
this.isOn = false;
System.out.println("Công tắc đã được lắp đặt. Hiện đang: TẮT");
}
// Phương thức để BẬT công tắc
public void turnOn() {
if (!isOn) { // Nếu đang TẮT thì mới BẬT
this.isOn = true;
System.out.println("Công tắc: BẬT.");
} else {
System.out.println("Ơ kìa, công tắc đang BẬT rồi mà, muốn BẬT nữa hả?");
}
}
// Phương thức để TẮT công tắc
public void turnOff() {
if (isOn) { // Nếu đang BẬT thì mới TẮT
this.isOn = false;
System.out.println("Công tắc: TẮT.");
} else {
System.out.println("Công tắc đang TẮT rồi mà, muốn TẮT nữa hả?");
}
}
// Phương thức để ĐỔI trạng thái (Bật -> Tắt, Tắt -> Bật)
public void toggle() {
if (isOn) {
turnOff();
} else {
turnOn();
}
}
// Getter để kiểm tra trạng thái hiện tại
public boolean isOn() {
return isOn;
}
// Phương thức để in ra trạng thái hiện tại một cách thân thiện
public String getCurrentState() {
return isOn ? "ON" : "OFF";
}
public static void main(String[] args) {
LightSwitch myRoomSwitch = new LightSwitch(); // Tạo một công tắc mới
System.out.println("Trạng thái ban đầu: " + myRoomSwitch.getCurrentState()); // Output: Trạng thái ban đầu: OFF
myRoomSwitch.turnOn(); // Output: Công tắc: BẬT.
System.out.println("Trạng thái hiện tại: " + myRoomSwitch.getCurrentState()); // Output: Trạng thái hiện tại: ON
myRoomSwitch.turnOn(); // Output: Ơ kìa, công tắc đang BẬT rồi mà, muốn BẬT nữa hả?
myRoomSwitch.toggle(); // Output: Công tắc: TẮT.
System.out.println("Trạng thái sau khi toggle: " + myRoomSwitch.getCurrentState()); // Output: Trạng thái sau khi toggle: OFF
myRoomSwitch.turnOff(); // Output: Công tắc đang TẮT rồi mà, muốn TẮT nữa hả?
}
}
Trong ví dụ trên, biến isOn chính là state của đối tượng LightSwitch. Các phương thức turnOn(), turnOff(), toggle() thay đổi state này và hành vi của chúng cũng phụ thuộc vào state hiện tại.

3. Mẹo Hay (Best Practices) từ Giảng viên Creyt
Để quản lý state một cách "chill" nhất, anh Creyt có vài tips cho các em:
-
Encapsulation (Đóng gói): Giấu state đi! Luôn luôn khai báo các biến state là
private. Đừng bao giờ cho phép code bên ngoài truy cập và thay đổi state một cách trực tiếp. Hãy nghĩ đến profile Instagram của bạn: bạn không cho ai vào chỉnh sửa trực tiếp tên, ảnh đại diện của mình đúng không? Phải qua các nút "Edit Profile" có sẵn. Tương tự, chỉ cho phép thay đổi state thông qua các phương thứcpubliccủa đối tượng (nhưturnOn(),turnOff()ở trên). Điều này giúp kiểm soát luồng dữ liệu và tránh những thay đổi "ngoài luồng" gây bug khó hiểu. -
Immutability (Bất biến) khi có thể: Nếu một state không cần thay đổi sau khi đối tượng được tạo, hãy làm cho nó bất biến bằng cách dùng từ khóa
finalvà không cung cấp setter. Ví dụ, ngày sinh của một người thường không thay đổi. Đối tượng bất biến giúp code dễ dự đoán hơn, ít lỗi hơn trong môi trường đa luồng, và dễ debug hơn nhiều.Stringtrong Java là một ví dụ điển hình của đối tượng bất biến. -
State Pattern (Nâng cao): Khi đối tượng của bạn có quá nhiều trạng thái, và mỗi trạng thái lại có hành vi khác nhau đáng kể, việc dùng quá nhiều
if-elsehayswitch-caseđể kiểm tra trạng thái sẽ biến code thành một "mớ bòng bong" khó quản lý. Lúc này, hãy nghĩ đến State Pattern. Nó cho phép đối tượng thay đổi hành vi của mình khi trạng thái nội tại thay đổi, giống như đối tượng "đổi vai" vậy. Mỗi trạng thái sẽ được đại diện bởi một class riêng, giúp code sạch sẽ, dễ mở rộng và dễ bảo trì hơn. -
Keep State Minimal (Giữ state tối thiểu): Đừng "tham lam" lưu trữ những thông tin không cần thiết vào state của đối tượng. "Gánh" ít đồ thì đi nhanh hơn, code cũng vậy. Chỉ lưu những gì thực sự cần để đối tượng hoạt động đúng và thể hiện hành vi của nó.
4. Góc nhìn Harvard (dễ hiểu tuyệt đối)
Từ góc độ học thuật mà vẫn dễ hiểu, State là một trong những trụ cột định hình bản chất của một đối tượng trong lập trình hướng đối tượng. Nó không chỉ là một tập hợp các giá trị, mà còn là bản chất động học của đối tượng. State cung cấp ngữ cảnh cho các hành vi của đối tượng, biến các phương thức từ những hàm độc lập thành những tác vụ có ý nghĩa, được điều chỉnh bởi tình hình hiện tại của đối tượng.
Quản lý State hiệu quả là chìa khóa để thiết kế các hệ thống mạnh mẽ, dễ bảo trì và mở rộng. Nó liên quan trực tiếp đến nguyên tắc Single Responsibility Principle (SRP) – mỗi đối tượng nên có một trách nhiệm duy nhất. Khi State được quản lý tốt, trách nhiệm của đối tượng trở nên rõ ràng hơn, và sự thay đổi State sẽ dẫn đến sự thay đổi hành vi một cách logic và có kiểm soát.
5. Ví dụ thực tế: Ứng dụng/Website đã ứng dụng State
State là một khái niệm cực kỳ phổ biến và được ứng dụng ở khắp mọi nơi, từ những app bạn dùng hàng ngày đến các hệ thống phức tạp:
-
Game Development: Một nhân vật trong game (ví dụ: Liên Quân Mobile) có các state như
health(máu),mana(năng lượng),score(điểm),equippedItems(vật phẩm đang trang bị),currentLevel(cấp độ hiện tại). Các hành động như "tấn công", "hồi máu", "lên cấp" đều thay đổi state của nhân vật. -
E-commerce (Shopee, Tiki): Giỏ hàng của bạn có state là
empty(trống),itemsAdded(đã thêm món),checkoutInProgress(đang thanh toán). Trạng thái đơn hàng cũng là một state quan trọng:pending(chờ xác nhận),shipped(đã gửi),delivered(đã giao),cancelled(đã hủy). -
Social Media (Facebook, Instagram): Trạng thái hoạt động của người dùng (
online,offline,away), trạng thái của một bài đăng (draft,published,archived), trạng thái của yêu cầu kết bạn (pending,accepted,rejected). -
Hệ điều hành: Trạng thái của một tiến trình (
running,waiting,terminated), trạng thái của một file (open,closed).
6. Thử nghiệm và Nên dùng cho case nào?
Khi nào nên dùng State?
Câu trả lời rất đơn giản: Hầu như mọi lúc khi bạn tạo một đối tượng! Mọi đối tượng đều có state, dù ít hay nhiều. Vấn đề không phải là có dùng State hay không, mà là bạn quản lý State đó như thế nào để code của bạn hiệu quả, dễ đọc và dễ bảo trì.
Nên dùng State Pattern (phiên bản nâng cao của việc quản lý state) khi:
- Một đối tượng có nhiều trạng thái và hành vi của nó thay đổi đáng kể tùy thuộc vào trạng thái hiện tại. Ví dụ: một đối tượng
Ordercó thể có các trạng tháiNew,Paid,Shipped,Delivered,Cancelled, và các hành động nhưprocessPayment()sẽ có ý nghĩa khác nhau ở mỗi trạng thái. - Mã nguồn của bạn bắt đầu có quá nhiều câu lệnh
if-elsehoặcswitch-caseđể kiểm tra trạng thái và thực hiện các hành động khác nhau. Đây là dấu hiệu rõ ràng cho thấy bạn cần một cách tiếp cận cấu trúc hơn. - Bạn muốn dễ dàng thêm các trạng thái mới vào hệ thống mà không cần phải sửa đổi nhiều mã nguồn hiện có (tuân thủ nguyên tắc Open/Closed Principle).
Thử nghiệm tại nhà:
- Tạo một Class
Player: Hãy định nghĩa các state nhưhealth(int),mana(int),isAlive(boolean). Viết các phương thứctakeDamage(int damage),heal(int amount),useSkill(int manaCost)và xem cách chúng thay đổi state củaPlayer. - Tạo một Class
TrafficLight(Đèn giao thông): Định nghĩa statecurrentColor(có thể là enumRED,YELLOW,GREEN). Viết phương thứcchangeLight()để chuyển đổi tuần tự giữa các màu. Hãy nghĩ xem hành vi của đèn (ví dụ:allowTraffic()) sẽ thay đổi như thế nào tùy theocurrentColor.
Nhớ nhé, State là trái tim của mọi đối tượng. Nắm vững nó, bạn sẽ tự tin hơn rất nhiều khi thiết kế các hệ thống phức tạp! Chúc các em "code" vui vẻ!
Thuộc Series: Java – OOP
Bài giảng này được tự động xuất bản ngẫu nhiên từ thư viện kiến thức. Đừng quên đón xem các Từ khoá Hướng Dẫn tiếp theo nhé!