考虑下面的MouseListener。我的问题是:具有此监听器提供的额外功能,其中一些您不需要,值得拥有这些功能所带来的内存和处理开销?或者应该避免这种“冗长”的实施?
import java.awt.Component;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.Timer;
/**
* This is an overkill class that is useful for distinguishing between buttons and includes functions for hold and double-click events.
*
* @author Paranoid Android
*/
public class ParanoidMouseListener extends MouseAdapter {
public static final int LEFT = MouseEvent.BUTTON1;
public static final int MIDDLE = MouseEvent.BUTTON2;
public static final int RIGHT = MouseEvent.BUTTON3;
private DoubleClickTimer leftDouble = new DoubleClickTimer();
private DoubleClickTimer middleDouble = new DoubleClickTimer();
private DoubleClickTimer rightDouble = new DoubleClickTimer();
private MouseEvent event;
private int pressedButton;
private Component pressed;
private boolean dragging;
/**
* This method allows methods to ignore the MouseEvent when not needed.
*
* @return the latest mouse event.
*/
public MouseEvent getEvent() {
return event;
}
private HoldTimer leftHold = new HoldTimer() {
@Override
public void perform() {
onLeftHold();
}
};
private HoldTimer middleHold = new HoldTimer() {
@Override
public void perform() {
onMiddleHold();
}
};
private HoldTimer rightHold = new HoldTimer() {
@Override
public void perform() {
onRightHold();
}
};
@Override
public final void mouseClicked(MouseEvent event) {
this.event = event;
switch (event.getButton()) {
case LEFT:
if (leftDouble.isRunning()) {
leftDouble.stop();
onLeftDoubleClick();
} else {
leftDouble.start();
onPureLeftClick();
}
break;
case MIDDLE:
if (middleDouble.isRunning()) {
middleDouble.stop();
onMiddleDoubleClick();
} else {
middleDouble.start();
onPureMiddleClick();
}
break;
case RIGHT:
if (rightDouble.isRunning()) {
rightDouble.stop();
onRightDoubleClick();
} else {
rightDouble.start();
onPureRightClick();
}
break;
}
}
@Override
public final void mousePressed(MouseEvent event) {
this.event = event;
pressedButton = event.getButton();
pressed = event.getComponent();
switch (event.getButton()) {
case LEFT:
leftHold.start();
onLeftPress();
break;
case MIDDLE:
middleHold.start();
onMiddlePress();
break;
case RIGHT:
rightHold.start();
onRightPress();
break;
}
}
@Override
public final void mouseReleased(MouseEvent event) {
this.event = event;
pressedButton = -1;
Component src = event.getComponent();
boolean contains = src.contains(event.getPoint());
switch (event.getButton()) {
case LEFT:
leftHold.stop();
onLeftRelease();
if (!dragging && src == pressed && contains) onLeftClick();
break;
case MIDDLE:
middleHold.stop();
onMiddleRelease();
if (!dragging && src == pressed && contains) onMiddleClick();
break;
case RIGHT:
rightHold.stop();
onRightRelease();
if (!dragging && src == pressed && contains) onRightClick();
break;
}
dragging = false;
}
@Override
public final void mouseMoved(MouseEvent event) {
this.event = event;
moved();
}
@Override
public final void mouseDragged(MouseEvent event) {
this.event = event;
dragging = true;
switch (pressedButton) {
case LEFT:
onLeftDrag();
break;
case MIDDLE:
onMiddleDrag();
break;
case RIGHT:
onRightDrag();
break;
}
}
@Override
public final void mouseEntered(MouseEvent event) {
this.event = event;
entered();
}
@Override
public final void mouseExited(MouseEvent event) {
this.event = event;
exited();
}
private int getDoubleClickInterval() {
String property = "awt.multiClickInterval";
return (int) Toolkit.getDefaultToolkit().getDesktopProperty(property);
}
private class DoubleClickTimer extends Timer {
public DoubleClickTimer() {
super(getDoubleClickInterval(), null);
this.setRepeats(false);
}
}
public int getHoldInitialDelay() {
return 300;
}
public int getHoldQueueDelay() {
return 60;
}
private class HoldTimer extends Timer {
public HoldTimer() {
super(getHoldQueueDelay(), null);
this.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
perform();
}
});
this.setInitialDelay(getHoldInitialDelay());
}
public void perform() {
}
}
public void moved() {
}
public void entered() {
}
public void exited() {
}
public void onLeftHold() {
}
public void onMiddleHold() {
}
public void onRightHold() {
}
public void onLeftClick() {
}
public void onMiddleClick() {
}
public void onRightClick() {
}
public void onPureLeftClick() {
}
public void onPureMiddleClick() {
}
public void onPureRightClick() {
}
public void onLeftDoubleClick() {
}
public void onMiddleDoubleClick() {
}
public void onRightDoubleClick() {
}
public void onLeftPress() {
}
public void onMiddlePress() {
}
public void onRightPress() {
}
public void onLeftRelease() {
}
public void onMiddleRelease() {
}
public void onRightRelease() {
}
public void onLeftDrag() {
}
public void onMiddleDrag() {
}
public void onRightDrag() {
}
}
答案 0 :(得分:2)
正如Hovercraft Full Of Eels在评论中指出的那样,这是You Aren't Gonna Need It的经典案例。在明确了解谁将使用它以及何时使用它之前实现功能通常是禁止的。在这种情况下,考虑到您在评论中概述的用例,您有以下几种选择:
在任何地方使用此类并接受稍高的开销。很可能你不太关心性能影响,这可能非常小。但是,这确实会在代码的其余部分中引入对此类的更大依赖性,这意味着如果您在以后引入回归,则存在破坏大量相关系统的风险。
允许班级的消费者指出他们将使用哪些功能(例如,双击)并禁用消费者不想要的功能。这会给您的课程带来复杂性,并使其更容易出错,并且使测试变得更加困难(尽管几乎不可能)。如果类之间非常需要一致性,这可能是一种选择。
需要添加的功能时使用此类,并在其他地方使用普通的MouseAdapter
。这可能是您的最佳选择,尤其是在您的自定义类中未定义某些行为案例时。这减少了对类的依赖,并在内部简化了类。权衡的是消费者类之间处理鼠标交互的方式的一致性较低,以及为消费者实现MouseAdapter
稍微多一些的代码 - 通常是值得的权衡。
答案 1 :(得分:1)
如果您需要这些附加功能,则别无选择!如果你不需要这些功能,那么使用这个扩展的监听器类是没有意义的,再也没有选择!
请注意一些成员字段和一些其他代码,与其他Java VM和其他代码相比,它几乎没有开销...所以要么选择:它并不重要!
再次:选择你需要的东西!