java - 什么java设计模式可以避免强制转换数据实体
问题描述
我目前正在我的应用程序中实现类似异步的事件队列 - 它被设计为这样工作:一个组件对一些用户输入做出反应并将事件放入队列,另一个“侦听器”正在检查是否存在特定类型的事件在队列中运行它自己的业务逻辑
可以有各种事件类型(如 USER_MOUSE_CLICK、USER_KEYBOARD_CLICK 等),每个实现都有自己的“事件对象”类型
它看起来像这样(我正在省略构造函数 - 设置所有字段和 getter/setter - 它们只是普通的默认值):
public abstract MyEvent<T> {
private EventType eventType;
private T eventData;
}
public MouseClickEvent extends MyEvent<ClickPoint> { // ClickPoint class contains x,y of mouse click
public MouseClick(ClickPoint point) {
super(EventType.USER_MOUSE_CLICK, point);
}
}
public KeyboardClickEvent extends MyEvent<String> { // character that has been clicked on keyboard
public MouseClick(String key) {
super(EventType.USER_KEYBOARD_CLICK, key);
}
}
我还有一个带有MyEvent
实例队列的服务以及检索提供的第一个事件(EventType
如果存在)的方法 - 它看起来像
...
private List<MyEvent> queue;
...
public MyEvent fetchMyEvent(EventType eventType) {
for(MyEvent event : queue) {
if(event.getEventType().equals(eventType) {
return event;
}
}
return null;
}
...
问题是,当我尝试检索事件时,我需要将其转换为特定的实现,例如
// some listener logic
MouseClickEvent event = (MouseClickEvent ) eventService.fetchMyEvent(EventType.USER_MOUSE_CLICK);
log("The X point of mouse click was: " + event.getEventData().x);
我不喜欢这种强制转换——我觉得当我获取事件时我无法控制类型,我认为这种情况就像一个“弱点”和错误生成器。是否有任何设计模式可以避免这种情况,或者我应该重新设计整个系统?或者也许这是唯一的方法,我不应该关心
解决方案
我建议您使用访客模式以避免强制转换。你是对的,铸造应该谨慎使用。
要使用访问者模式,您必须:首先:定义访问者界面:
public interface IEventVisitor {
void visit(MouseClickEvent event);
void visit(KeyboardClickEvent event);
}
第二个在你的晚餐类中定义一个抽象方法接受:
public abstract MyEvent<T> {
private EventType eventType;
private T eventData;
public abstract void accept(IEventVisitor visitor);
}
第三:将每个子类的方法实现为:
public MouseClickEvent extends MyEvent<ClickPoint> { // ClickPoint class contains x,y of mouse click
public MouseClick(ClickPoint point) {
super(EventType.USER_MOUSE_CLICK, point);
}
public void accept(IEventVisitor visitor) {
visitor.visit(this);
}
}
最后实现您的访问者界面。
使用将如下所示,实例化访问者并调用 event.accept(visitor)。
Event event = eventService.fetchMyEvent(EventType.USER_MOUSE_CLICK);
IEventVisitor visitor = new IEventVisitor() {
@Override
public void visit(MouseClickEvent event) {
// logic goes here
}
@Override
public void visit(KeyboardClickEvent event) {
// logic goes here
}
};
event.accept(visitor);
推荐阅读
- java - 如何修复方法参考中的错误返回类型:无法将 RecipeIndicatorsDto 转换为 R?
- arrays - Mongoose findone() 返回特定字段
- javascript - 图像旋转未捕获的 ReferenceError
- c++ - 我能用这个进程做什么返回-1073741819
- python - 使用 python-firefox-selenium 填写表单并将重定向页面下载为 pdf
- java - javafx 11 随机触发事件?
- amazon-web-services - Aws S3 和 Mailchimp:将新订阅者的免费下载权限限制为实际收到“带有下载链接的订阅电子邮件”的人
- c# - User.IsInRole 结果不正确
- excel - 找不到对象时如何进行?
- java - 为类创建文件夹的 Java makefile