Bạn không thể thực hiện điều này trực tiếp trong một lớp vì định nghĩa lớp bên dưới không thể được biên dịch do xóa các kiểu chung và khai báo giao diện trùng lặp.
class TwoTypesConsumer implements Consumer<Apple>, Consumer<Tomato> {
// cannot compile
...
}
Bất kỳ giải pháp nào khác để đóng gói các hoạt động tiêu thụ giống nhau trong một lớp đều yêu cầu xác định lớp của bạn là:
class TwoTypesConsumer { ... }
Điều này là vô nghĩa khi bạn cần lặp lại / sao chép định nghĩa của cả hai thao tác và chúng sẽ không được tham chiếu từ giao diện. IMHO làm điều này là một sự trùng lặp mã nhỏ và xấu mà tôi đang cố gắng tránh.
Đây cũng có thể là một chỉ báo cho thấy có quá nhiều trách nhiệm trong một lớp để tiêu thụ 2 đối tượng khác nhau (nếu chúng không được ghép nối).
Tuy nhiên, những gì tôi đang làm và những gì bạn có thể làm là thêm đối tượng nhà máy rõ ràng để tạo người tiêu dùng được kết nối theo cách sau:
interface ConsumerFactory {
Consumer<Apple> createAppleConsumer();
Consumer<Tomato> createTomatoConsumer();
}
Nếu trong thực tế các loại đó thực sự được ghép nối (liên quan) thì tôi khuyên bạn nên tạo một triển khai theo cách như sau:
class TwoTypesConsumerFactory {
// shared objects goes here
private class TomatoConsumer implements Consumer<Tomato> {
public void consume(Tomato tomato) {
// you can access shared objects here
}
}
private class AppleConsumer implements Consumer<Apple> {
public void consume(Apple apple) {
// you can access shared objects here
}
}
// It is really important to return generic Consumer<Apple> here
// instead of AppleConsumer. The classes should be rather private.
public Consumer<Apple> createAppleConsumer() {
return new AppleConsumer();
}
// ...and the same here
public Consumer<Tomato> createTomatoConsumer() {
return new TomatoConsumer();
}
}
Ưu điểm là lớp nhà máy biết cả hai triển khai, có trạng thái chia sẻ (nếu cần) và bạn có thể trả lại nhiều người tiêu dùng được ghép nối hơn nếu cần. Không có khai báo phương thức tiêu thụ lặp lại mà không xuất phát từ giao diện.
Xin lưu ý rằng mỗi người tiêu dùng có thể là lớp độc lập (vẫn riêng tư) nếu họ không hoàn toàn liên quan.
Nhược điểm của giải pháp đó là độ phức tạp của lớp cao hơn (ngay cả khi đây có thể là một tệp java) và để truy cập phương thức tiêu thụ, bạn cần thêm một cuộc gọi thay vì:
twoTypesConsumer.consume(apple)
twoTypesConsumer.consume(tomato)
bạn có:
twoTypesConsumerFactory.createAppleConsumer().consume(apple);
twoTypesConsumerFactory.createTomatoConsumer().consume(tomato);
Để tóm tắt, bạn có thể định nghĩa 2 người tiêu dùng chung trong một lớp cấp cao nhất bằng cách sử dụng 2 lớp bên trong nhưng trong trường hợp gọi bạn cần có một tham chiếu trước cho người tiêu dùng thực hiện phù hợp vì đây không thể chỉ là một đối tượng người tiêu dùng.