3 回答
TA贡献1830条经验 获得超9个赞
根据实际逻辑,LetterSender并且PackageSender确实可能有两个不同的方法,每个方法都有一个不同的参数。对于第一个:
public void send(Letter letter);
对于第二个:
public void send(Package letter);
为了从多态中受益,您应该定义在这两个类实现的接口中定义的公共方法。例如 :
public interface MailSender{
void send(Mail mail);
}
但是在 Java 中,参数对于overriding. 所以你不能通过对Mail参数进行子类型化来实现接口。
所以这意味着你必须void send(Mail mail)在两个 Sender 类中实现,例如:
public class LetterSender implements MailSender{
@Override
public void send(Mail mail){
// ...
}
}
public class PackageSender implements MailSender{
@Override
public void send(Mail mail){
// ...
}
}
要实现它,您应该Mail从高层次的角度定义任何子Mail类所需的行为/方法。
每个Mail子类都会为它们定义实现。
因此,两个发送方实现可以send(Mail mail)在不需要向下转换参数的情况下进行处理。
TA贡献1780条经验 获得超3个赞
您可以为此使用访问者模式。
定义一个接口 MailVisitor 为:
public interface MailVisitor {
void visitLetter(Letter letter);
void visitPackage(Package package);
}
在 MailSender 中实现这个接口:
public class MailSender implement MailVisitor {
@Override
public void visitLetter(Letter letter) {//letter sending goes here}
@Override
public void visitPackage(Package package) {//package sending goes here}
}
现在在 PostOffice 类中,您让 MailSender 访问刚刚到达的邮件包:
public class PostOffice {
@Inject
private MailSender mailSender;
public void send(Mail mail) {
mail.visit(mailSender);
}
}
访问方法实现如下:
public abstract class Mail {
public abstract void visit(MailVisitor visitor);
}
public class Letter extends Mail {
public void visit(MailVisitor visitor) {
visitor.visitLetter(this);
}
}
public class Package extends Mail {
public void visit(MailVisitor visitor) {
visitor.visitPackage(this);
}
}
当我第一次遇到它时,我花了一段时间才完全掌握它是如何工作的。但它是一种非常强大的设计模式,它允许您消除每个 instanceof + cast 操作。
这样做的最大优点是当您定义一个新的 Mail 子类时,比如说 AirMail。编译器将强制您实现visit(MailVisitorvisitor) 方法。这将自动让您在 MailVisitor 上定义一个新方法。这将反过来迫使您在 MailSender 类中实现该新方法。因此,除非您定义了能够处理新创建的子类型的逻辑,否则您的代码将无法编译。而如果您使用了 if 语句,您可能只是忘记为 AirMail 添加一个新分支,这将使您的应用程序无法发送任何需要飞机运输的邮件:)
TA贡献1893条经验 获得超10个赞
这类问题可以通过几种不同的方式解决。最简单的版本是责任链:
interface Sender {
boolean canSend(Mail mail);
void send(Mail mail);
}
...
List<Sender> senders;
...
senders.stream()
.filter(s -> s.canSend(mail))
.findAny()
.ifPresentOrElseThrow(
s -> s.send(mail),
() -> new SomethingException()
);
添加回答
举报