如何删除运算符“ instanceof”并将其替换为多态? NamedPlace和DescribedPlace都是主类Place的子类。
class RightClickListener extends MouseAdapter {
@Override
public void mouseClicked(MouseEvent mev) {
p = (Place) mev.getSource();
if (mev.getModifiers() == InputEvent.BUTTON3_MASK) {
if (p instanceof NamedPlace) {
JOptionPane.showMessageDialog(null, p.getName() + " " + p.getPosition(), "Platsinfo: ", JOptionPane.INFORMATION_MESSAGE);
}
if (p instanceof DescribedPlace) {
JOptionPane describedPane = new JOptionPane();
describedPane.setMessage("Name: " + p.getName() + " " + p.getPosition() + "\n" + "Description: " + ((DescribedPlace) p).getDescription());
describedPane.setMessageType(JOptionPane.INFORMATION_MESSAGE);
JDialog dialog = describedPane.createDialog(p, "Platsinfo:");
dialog.setVisible(true);
}
}
}
}
答案 0 :(得分:2)
您可以为Place
提供抽象方法,并将实现添加到子类中。
abstract class Place {
// ..
public abstract void action();
}
class NamedPlace extends Place {
public void action() {
JOptionPane.showMessageDialog(null, p.getName() + " " + p.getPosition(), "Platsinfo: ", JOptionPane.INFORMATION_MESSAGE);
}
}
class DescribedPlace extends Place {
public void action() {
JOptionPane describedPane = new JOptionPane();
describedPane.setMessage("Name: " + p.getName() + " " + p.getPosition() + "\n" + "Description: " + ((DescribedPlace) p).getDescription());
describedPane.setMessageType(JOptionPane.INFORMATION_MESSAGE);
JDialog dialog = describedPane.createDialog(p, "Platsinfo:");
dialog.setVisible(true);
}
}
,然后在侦听器中使用它。
class RightClickListener extends MouseAdapter {
@Override
public void mouseClicked(MouseEvent mev) {
p = (Place) mev.getSource();
if (mev.getModifiers() == InputEvent.BUTTON3_MASK) {
p.action();
}
}
}
但是,根据Place
的确切含义,这可能不是一个好主意(例如,如果它不是GUI类)。
答案 1 :(得分:0)
唯一的方法是首先向基类中添加一个像doTheThing()
这样的抽象方法。
这样您就可以在该侦听器中简单地调用p.doTheThing()
。
当然,NamedPlace实现了该方法:
JOptionPane.showMessageDialog(null, p.getName() + " " + p.getPosition(), "Platsinfo: ", JOptionPane.INFORMATION_MESSAGE);
和另一个类实现它
JOptionPane describedPane = new JOptionPane();
...
从技术上讲,这可以满足您的要求,但这也不是一个很好的解决方案。由于这两种方法的作用确实不同。
一个 more 合理的解决方案可能是您有一个抽象方法,该方法例如返回一个(格式化的)字符串,然后将其添加到一个(统一的)消息窗口中,或类似的方法。
多态性的目的是允许使用通用接口执行“相似”的操作。在相同的环境下做完全不同的事情无济于事。
答案 2 :(得分:0)
如果您的Place
类不知道单击的特定响应实现,则可以使用visitor pattern,并将Place
层次结构与其响应实现分开。< / p>
然后,您可以针对不同情况提供不同的实现,并且Place
类将不会增长,并且会与越来越多的情况特定代码紧密结合。
要实现此目的,请使用其他方法更新您的父类(我更喜欢使用接口)Place
:
public interface Place {
void accept(Visitor visitor);
}
并实现它:
public final class NamedPlace {
@Override
public void accept(Visitor visitor) {
visitor.visitNamedPlace(this);
}
}
public final class DescribedPlace {
@Override
public void accept(Visitor visitor) {
visitor.visitDescribedPlace(this);
}
}
现在访问者界面将如下所示:
public interface Visitor {
void visitNamedPlace(NamedPlace place);
void visitDescribedPlace(DescribedPlace place);
}
访问者模式现已准备就绪。并在您的示例中使用它:
class RightClickListener extends MouseAdapter {
@Override
public void mouseClicked(MouseEvent mev) {
((Place) mev.getSource()).accept(new Visitor() {
@Override
public void visitNamedPlace(NamedPlace p) {
JOptionPane.showMessageDialog(null, p.getName() + " " + p.getPosition(), "Platsinfo: ", JOptionPane.INFORMATION_MESSAGE);
}
@Override
public void visitDescribedPlace(DescribedPlace p) {
JOptionPane describedPane = new JOptionPane();
describedPane.setMessage("Name: " + p.getName() + " " + p.getPosition() + "\n" + "Description: " + ((DescribedPlace) p).getDescription());
describedPane.setMessageType(JOptionPane.INFORMATION_MESSAGE);
JDialog dialog = describedPane.createDialog(p, "Platsinfo:");
dialog.setVisible(true);
}
});
}
}
}
您的选择实际上是:
这取决于您的用例。