ISP — Interface nhỏ, đúng việc
Nội dung bài · 5 mục
- 1.Khái niệm
- 2.Ví dụ
- 3.Thử ngay
- 4.Lỗi hay gặp
- 5.Tóm tắt
Interface OrderStore có ba method: đọc, lưu, xoá. Trang báo cáo chỉ cần
đọc nhưng vẫn phải implement đủ ba method, hai method thừa chỉ ném
UnsupportedOperationException. ISP tránh việc ép class nhận những thứ nó không dùng.
Khái niệm
✂️ ISP (Interface Segregation Principle): không bắt class phụ thuộc vào những method nó không dùng, nên chia interface lớn thành nhiều interface nhỏ theo từng việc.
Ví dụ
// Main.java
void main() {
var repo = new OrderRepository();
var page = new ReportPage(repo);
page.show();
}
// OrderReader.java
interface OrderReader {
String get(int id);
}
// OrderWriter.java
interface OrderWriter {
void save(String order);
}
// OrderRepository.java
class OrderRepository
implements OrderReader, OrderWriter {
@Override
public String get(int id) {
return "Đơn #" + id;
}
@Override
public void save(String order) {
System.out.println("Lưu " + order);
}
}
// ReportPage.java
class ReportPage {
private final OrderReader reader;
public ReportPage(OrderReader reader) {
this.reader = reader;
}
public void show() {
System.out.println(reader.get(1));
}
}OrderReaderchỉ đọc,OrderWriterchỉ ghi. Mỗi interface một việc.OrderRepositorylàm được cả hai nên implement cả hai.ReportPagechỉ cần đọc nên chỉ nhậnOrderReader. Sửa phần ghi không ảnh hưởng tới nó.
Thử ngay
Giữ các file của ví dụ, thêm hai dòng sau vào main, ngay dưới
page.show();:
OrderWriter writer = repo;
writer.save("Đơn #2");Đoán trước khi chạy: cùng một object repo, vừa truyền cho
ReportPage như một OrderReader, vừa gán vào biến OrderWriter. Có
được không?
Xem kết quả
Đơn #1
Lưu Đơn #2Được. Object implement nhiều interface thì đóng được vai của từng interface đó. Mỗi nơi chỉ thấy đúng phần nó cần.
Lỗi hay gặp
Interface quá to, class phải implement cho có.
UnsupportedOperationException là dấu hiệu rõ nhất.
// SAI — trang báo cáo bị ép implement cả ghi và xoá
// OrderStore.java
interface OrderStore {
String get(int id);
void save(String order);
void delete(int id);
}
// ReportSource.java
class ReportSource implements OrderStore {
@Override
public String get(int id) {
return "Đơn #" + id;
}
@Override
public void save(String order) {
throw new UnsupportedOperationException();
}
@Override
public void delete(int id) {
throw new UnsupportedOperationException();
}
}// ĐÚNG — trang báo cáo chỉ implement phần đọc
// ReportSource.java
class ReportSource implements OrderReader {
@Override
public String get(int id) {
return "Đơn #" + id;
}
}Tóm tắt
- ISP: không bắt class phụ thuộc vào method nó không dùng.
- Chia interface lớn thành nhiều interface nhỏ theo từng việc.
- Một class implement được nhiều interface nhỏ khi nó làm được nhiều việc.
UnsupportedOperationExceptiontrong class implement là dấu hiệu interface quá to.
Tự kiểm tra
0/3 câuInterface OfficeMachine có print(), scan(), fax(). Máy in rẻ chỉ in được, nên scan() và fax() ném UnsupportedOperationException. Theo ISP nên làm gì?
Class Dashboard chỉ đọc dữ liệu đơn hàng. Constructor của nó nên nhận kiểu nào?
Interface AccountService có login(), logout(), changePassword() và được năm class implement. Team thêm resetPassword() vào interface này, không viết thân default. Class nào phải sửa?