Null Object được sử dụng để thay thế cho phép kiểm tra một giá trị null
có thể nhận xuất hiện.
Một object
Null được tạo ra để đại diện cho trường hợp vô nghĩa của một class
thực thể
và có thể được triển khai một số phương thức đáp ứng mặc định trong trường hợp dữ liệu
truy vấn không khả dụng. Null Object được xếp vào nhóm các pattern Hành Vi.
Áp dụng triển khai
Ở đây chúng ta có ví dụ mô tả về một đoạn xử lý yêu cầu đăng nhập từ người dùng.
Khi thông tin đăng nhập được gửi tới server, phần code main
sẽ kết nối tới cơ sở dữ liệu
database
để truy vấn tài khoản phù hợp. Nếu tập kết quả trả về sau khi truy vấn
bằng thông tin được cung cấp từ người dùng là một tập rỗng thì lệnh truy vấn sẽ trả
về một NullUser
thay vì trả về giá trị null
. Còn trong trường hợp có kết quả phù hợp
thì sẽ trả về một RealUser
mô tả thực thể người dùng.
Bạn lưu ý là mặc dù NullUser
cũng kế thừa từ AbstractUser
giống như RealUser
nhưng không cần phải triển khai các phương thức với code đáp ứng tới giao diện người dùng
ở front-end
. Phương thức quan trọng nhất là isNull()
cần được chắc chắn triển khai
trên cả RealUser
và NullUser
để sử dụng trong phép kiểm tra thay cho giá trị null
có khả năng xuất hiện. Các phương thức còn lại của NullUser
có thể trả về null
,
hoặcthrow Exception
, hoặc in thông báo ra console
để phục vụ debug
và chạy thử.
Bước 1
Tạo AbstractUser
để mô tả thực thể người dùng và tạo ràng buộc triển khai isNull()
cho các class kế thừa.
nullobject/AbstractUser.java
packagenullobject;publicabstractclassAbstractUser{protectedString username;protectedString password;publicabstractStringgetUsername();publicabstractvoidsetUsername(String username)throwsException;publicabstractStringgetPassword();publicabstractvoidsetPassword(String password)throwsException;publicabstractbooleanisNull();}
Bước 2
Tạo 2 class kế thừa AbstractUser
:
RealUser
để mô tả thực thể người dùngNullUser
để đại diện cho trường hợp kết quả truy vấn không khả dụng
nullobject/RealUser.java
packagenullobject;publicclassRealUserextendsAbstractUser{publicRealUser(String username,String password
){try{setUsername(username);setPassword(password);}catch(Exception e){
e.printStackTrace();}}@OverridepublicStringgetUsername(){return username;}@OverridepublicvoidsetUsername(String username)throwsException{if(username ==null|| username.equalsIgnoreCase("")){thrownewException("Tên người dùng không hợp lệ");}else{this.username = username;}}@OverridepublicStringgetPassword(){return password;}@OverridepublicvoidsetPassword(String password)throwsException{if(password ==null|| password.equalsIgnoreCase("")){thrownewException("Mật khẩu không hợp lệ");}else{this.password = password;}}@OverridepublicbooleanisNull(){returnfalse;}}
nullobject/NullUser.java
packagenullobject;publicclassNullUserextendsAbstractUser{@OverridepublicStringgetUsername(){returnnull;}@OverridepublicvoidsetUsername(String username)throwsException{thrownewException("Phương thức chưa có code triển khai");}@OverridepublicStringgetPassword(){returnnull;}@OverridepublicvoidsetPassword(String password)throwsException{thrownewException("Phương thức chưa có code triển khai");}@OverridepublicbooleanisNull(){returntrue;}}
Bước 3
Viết code main
để mô tả tiến trình xử lý yêu cầu đăng nhập.
PatternDemo.java
importnullobject.AbstractUser;importnullobject.NullUser;importnullobject.RealUser;importjava.util.ArrayList;importjava.util.List;publicclassPatternDemo{privatestaticList<AbstractUser> database =newArrayList<AbstractUser>();publicstaticvoidmain(String[] args){String inputUsername;String inputPassword;connectDatabase();//thử đăng nhập lần thứ nhấtSystem.out.println("==============");
inputUsername ="someone";
inputPassword ="qwerty123456789";userLogin(inputUsername, inputPassword);//thử đăng nhập lần thứ haiSystem.out.println("==============");
inputUsername ="semiart";
inputPassword ="123456789";userLogin(inputUsername, inputPassword);}privatestaticvoidconnectDatabase(){RealUser viblo =newRealUser("viblo","987654321");
database.add(viblo);RealUser semiart =newRealUser("semiart","123456789");
database.add(semiart);}privatestaticvoiduserLogin(String username,String password
){AbstractUser matched =queryUser(username, password);if(matched.isNull()){System.out.println("Thông tin đăng nhập không chính xác.");}else{System.out.println("Đăng nhập thành công!");System.out.println("Tên tài khoản: "+ matched.getUsername());}}privatestaticAbstractUserqueryUser(String username,String password
){List<AbstractUser> matchedUsers = database.stream()// filter lược bỏ những tài khoản không đúng với username// được cung cấp từ người dùng đang gửi yêu cầu đăng nhập.filter((user)-> user.getUsername().equals(username))// filter lược bỏ tiếp những tài khoản không đúng với password// được nhập vào bởi người dùng đang gửi yêu cầu đăng nhập.filter((user)-> user.getPassword().equals(password))// chuyển stream về lại giao diện List.toList();if(matchedUsers.isEmpty()){// nếu tập kết quả rỗng thì trả về một object NullreturnnewNullUser();}else{// nếu có kết quả phù hợp thì trả về phần tử duy nhấtreturn matchedUsers.get(0);}}}
Bước 4
Kiểm chứng lại kết quả được in ra ở console
.
console
==============Thông tin đăng nhập không chính xác.==============
Đăng nhập thành công!Tên tài khoản: semiart
Nguồn: viblo.asia