VieTopik
Tiếng HànTiếng Anh.NET (C#)Java
  • Góc học tập
Tải app
  • Thư viện
  • Luyện thi
  • Cẩm nang
  • Góc học tập
OOP và thiết kế (Java)SOLID
Bài 11/12
5 phút

ISP — Interface nhỏ, đúng việc

Nội dung bài · 5 mục
  1. 1.Khái niệm
  2. 2.Ví dụ
  3. 3.Thử ngay
  4. 4.Lỗi hay gặp
  5. 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));
    }
}
  • OrderReader chỉ đọc, OrderWriter chỉ ghi. Mỗi interface một việc.
  • OrderRepository làm được cả hai nên implement cả hai.
  • ReportPage chỉ cần đọc nên chỉ nhận OrderReader. Sửa phần ghi không ảnh hưởng tới nó.
<<interface>> OrderReader get(id) <<interface>> OrderWriter save(order) OrderRepository ReportPage
Một class làm hai vai, ReportPage chỉ thấy vai đọc

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.
  • UnsupportedOperationException trong class implement là dấu hiệu interface quá to.

Tự kiểm tra

0/3 câu
Câu 1

Interface 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ì?

Câu 2

Class Dashboard chỉ đọc dữ liệu đơn hàng. Constructor của nó nên nhận kiểu nào?

Câu 3

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?

LSP — Class con phải thay được class chaDIP và dependency injection

Nội dung bài

  1. 1.Khái niệm
  2. 2.Ví dụ
  3. 3.Thử ngay
  4. 4.Lỗi hay gặp
  5. 5.Tóm tắt