State được sử dụng để triển khai phương thức hoạt động của một class tùy theo điều kiện
cụ thể. Trong State, object chủ thể không chứa code triển khai của các phương thức hoạt động
mà thay vào đó sẽ ủy thác tới các object State
tương ứng với các trạng thái khác nhau
của thực thể mà chúng ta muốn mô tả. State được xếp vào nhóm các pattern Hành Vi.
Áp dụng triển khai
Ở đây chúng ta có một ví dụ về phiên bản desktop của phần mềm quản lý một trang blog nơi mọi người có thể đăng tải bài viết chia sẻ kiến thức. Sau khi người dùng đăng nhập và bắt đầu tạo một bài viết mới rồi nhấn nút "Lưu lại". Mặc định thì nút nhấn này sẽ lưu bài viết ở trạng thái "Bản nháp" và chỉ đến khi người viết bài thực hiện thao tác chọn "Công khai" thì bài viết mới được "Đăng tải". Như bạn thấy thì chức năng "Lưu lại" lúc này có cách thức hoạt động mang tính điều kiện và tùy thuộc vào trạng thái mà người dùng chọn để gắn nhãn cho bài viết.
Về mặt triển khai trong phần mềm, object Post
mô tả thực thể là một bài viết được
người dùng tạo ra. Tính năng save()
của Post
sẽ không chứa mã triển khai hành động
thực thi cụ thể mà ủy thác cho các object State
tương ứng với 2 trạng thái: bản nháp Draft
và bài đã được đăng tải Published
.
Bước 1
Tạo class Post
mô tả thực thể bài viết và abstract State
.
statepattern/Post.java
package statepattern; public class Post { private String title; private String author; private String body; private State state; public Post() { this.title = ""; this.author = ""; this.body = ""; state = new Draft(); } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public String getBody() { return body; } public void setBody(String body) { this.body = body; } public State getState() { return state; } public void setState(State state) { this.state = state; } public void save() { state.save(this); } public String toString() { return "Bài viết: " + title + "\n" + "Tác giả: " + author + "\n" + "Trạng thái: " + state.getName() + "\n" + "Nội dung: " + body; }
}
statepattern/State.java
package statepattern; public abstract class State { protected String name; public State(String name) { this.name = name; } public abstract void save(Post p); public String getName() { return name; }
}
Bước 2
Tạo 2 class trạng thái triển khai phương thức save()
.
statepattern/Draft.java
package statepattern; public class Draft
extends State { public Draft() { super("Bản nháp"); } @Override public void save(Post p) { System.out.println("Bài viết: " + p.getTitle() + " đã được lưu nháp."); }
}
statepattern/Published.java
package statepattern; public class Published
extends State { public Published() { super("Đã đăng tải"); } @Override public void save(Post p) { System.out.println("Bài viết: " + p.getTitle() + " đã được đăng tải."); }
}
Bước 3
Viết code main
để kiểm tra hoạt động của các State
.
PatternDemo.java
import statepattern.Post;
import statepattern.Published; public class PatternDemo { public static void main(String[] args) { Post p = new Post(); p.setTitle("State Pattern"); p.setAuthor("Semi Art"); p.setBody("Coming soon..."); p.save(); System.out.println("=============="); System.out.println(p); System.out.println("=============="); p.setTitle("[Design Patterns] State Pattern"); p.setBody("State có nghĩa là trạng thái."); p.setState(new Published()); p.save(); System.out.println("=============="); System.out.println(p); }
}
Bước 4
Kiểm chứng lại kết quả được in ra ở console
.
console
Bài viết: State Pattern đã được lưu nháp.
==============
Bài viết: State Pattern
Tác giả: Semi Art
Trạng thái: Bản nháp
Nội dung: Coming soon...
==============
Bài viết: [Design Patterns] State Pattern đã được đăng tải.
==============
Bài viết: [Design Patterns] State Pattern
Tác giả: Semi Art
Trạng thái: Đã đăng tải
Nội dung: State có nghĩa là trạng thái.