Các giao diện được sử dụng để xác định hành vi của một đối tượng. Điều này có nghĩa là tất cả các phương thức của giao diện được phơi bày. Khi sử dụng các phương thức mặc định, chúng tôi có thể cung cấp các triển khai tiêu chuẩn của các phương thức được xác định, cung cấp việc sử dụng lại mã qua các ranh giới lớp.
Trong một số trường hợp, chức năng là bắt buộc (có lẽ chỉ để sử dụng lại mã trong các phương thức mặc định khác nhau ) nhưng không nên bị lộ vì nó sẽ gây ô nhiễm không gian tên của lớp / đối tượng. Đây là nơi các phương thức mặc định riêng tư có ích. Ví dụ các phương thức mặc định riêng tư có thể là các nhà máy, xác nhận hoặc xử lý trạng thái mặc định.
package com.company;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public class Main {
public static void main(final String[] args) {
var messages =
List.of(
MessageQueue.newSubject("Message 1"),
MessageQueue.newTopic("Message 2"),
MessageQueue.newTopic("Message 3"));
final MessageQueueAdapter1 queue1 = () -> messages;
inspectQueue(queue1);
final MessageQueueAdapter2 queue2 = () -> messages;
inspectQueue(queue2);
}
private static void inspectQueue(final MessageQueue queue) {
final List<Message> messagesWithSubject = queue.getMessagesWithSubject();
assert messagesWithSubject.size() == 1 : "expected one message with 'Subject'";
final List<Message> messagesWithTopic = queue.getMessagesWithTopic();
assert messagesWithTopic.size() == 2 : "expected two message with 'Topic'";
assert !queue.getMessages().isEmpty() && 3 == queue.getMessages().size()
: "expected three messages in total";
}
@FunctionalInterface
interface Message {
private static boolean isPrefixedBy(final String message, final String prefix) {
return message != null && !message.isEmpty() && message.startsWith(prefix);
}
default boolean hasSubject() {
return isPrefixedBy(this.getMessage(), MessageQueue.PREFIX_SUBJECT);
}
default boolean hasTopic() {
return isPrefixedBy(this.getMessage(), MessageQueue.PREFIX_TOPIC);
}
String getMessage();
}
interface MessageQueue {
String PREFIX_SUBJECT = "Subject: ";
String PREFIX_TOPIC = "Topic: ";
private static Message newMessage(final String message) {
return () -> message;
}
static Message newSubject(final String message) {
return newMessage(PREFIX_SUBJECT + message);
}
static Message newTopic(final String message) {
return newMessage(PREFIX_TOPIC + message);
}
List<Message> getMessages();
List<Message> getMessagesWithSubject();
List<Message> getMessagesWithTopic();
}
@FunctionalInterface
interface MessageQueueAdapter1 extends MessageQueue {
private static List<Message> filterBy(
final List<Message> messages, final Predicate<Message> predicate) {
return messages.stream().filter(predicate).collect(Collectors.toList());
}
/** {@inheritDoc} */
@Override
default List<Message> getMessagesWithSubject() {
return filterBy(this.getMessages(), Message::hasSubject);
}
/** {@inheritDoc} */
@Override
default List<Message> getMessagesWithTopic() {
return filterBy(this.getMessages(), Message::hasTopic);
}
}
@FunctionalInterface
interface MessageQueueAdapter2 extends MessageQueue {
private List<Message> filterBy(final Predicate<Message> predicate) {
return this.getMessages().stream().filter(predicate).collect(Collectors.toList());
}
/** {@inheritDoc} */
@Override
default List<Message> getMessagesWithSubject() {
return filterBy(Message::hasSubject);
}
/** {@inheritDoc} */
@Override
default List<Message> getMessagesWithTopic() {
return filterBy(Message::hasTopic);
}
}
}