รูปแบบ state เป็นรูปแบบในกลุ่ม behavioural design pattern รูปแบบ state เป็นรูปแบบที่ช่วยให้โปรแกรมสามารถเปลี่ยนพฤติกรรมตามการเปลี่ยนสถานะภายในของโปรแกรม โดยสถานะภายในของโปรแกรมจะถูกแสดงด้วยคลาสที่แยกจากกันตามสถานะต่างๆของโปรแกรมโดยใช้คลาสแบบอินเตอร์เฟสหรือคลาสแบบแอบแสตรก คลาสที่มาใช้งานจะถือออบเจกต์ที่สอดคล้องตามสถานะปัจจุบันและแสดงพฤติกรรมตามที่กำหนดในออบเจกต์ รวมถึงให้ออบเจกต์ดังกล่าวจัดการเรื่องการเปลี่ยนสถานะด้วย และเมื่อมีการเปลี่ยนสถานะก็จะเปลี่ยนไปถือออบเจกต์อื่นที่สอดคล้องกับสถานะใหม่
การใช้รูปแบบ state ช่วยให้คลาสที่มาใช้งานไม่ต้องจัดการเรื่องสถานะเอง ทำให้เราสามารถเพิ่มสถานะอื่นในอนาคตได้โดยที่ไม่ต้องแก้ไขคลาสที่มาเรียกใช้งานเพราะตัวออบเจกต์ที่เป็นสถานะจะจัดการการเปลี่ยนแปลงเองด้วย
ตัวอย่างด้านล่างเป็นการใช้รูปแบบ state ในภาษาจาวา เริ่มจากสร้างคลาส Context ซึ่งเป็นโปรแกรมที่จะมีสถานะต่างๆ ซึ่งสถานะจะถูกเก็บที่ตัวแปร state โดยสถานะจะเป็นออบเจกต์ของคลาส State
// Context class
public class Context {
private State state;
public Context() {
state = new StateA();
}
public void setState(State state) {
this.state = state;
}
public void execute() {
state.execute(this);
}
}
เราใช้แนวทางภาพสรุปโดยใช้คลาสแบบอินเตอร์เฟส State เพื่อซ่อนสถานะต่างๆและเป็นส่วนเชื่อมต่อกับคลาสอื่น โดยกำหนดให้มีเมธอด execute() แต่จะไม่มีโปรแกรมเพราะเป็นเพียงภาพสรุปเท่านั้น
// State interface
public interface State {
void execute(Context context);
}
จากนั้นจึงสร้างคลาสของแต่ละสถานะและกำหนดอัลกอริธึให้เมธอด execute() ซึ่งก็คือเงื่อนไขในการเปลี่ยนสถานะ
// StateA class
public class StateA implements State {
@Override
public void execute(Context context) {
System.out.println(“Executing State A”);
context.setState(new StateB());
}
}
// StateB class
public class StateB implements State {
@Override
public void execute(Context context) {
System.out.println(“Executing State B”);
context.setState(new StateA());
}
}
ในการใช้งานอบเจกต์ Context จะเรียกใช้เมธอด execute ของสถานะเพื่อดำเนินการและเปลี่ยนสถานะของตนเอง
public static void main(String[] args) {
Context context = new Context();
context.execute(); // Output: Executing State A
context.execute(); // Output: Executing State B
context.execute(); // Output: Executing State A
}