在对我的项目进行一些重组时,我一直在尝试在我的代码中更好地利用面向对象的概念,但我不确定如何构建这种特殊情况:
方法可以触发三个可能的“事件”之一,每个事件都依赖于特定类型(播放器,块,世界),这些类型需要在运行时发生,因为它们是从文件反序列化的。为了简化执行路径,我将其构造成这样,因此它们都可以成为List的一部分,它只执行一个方法:
public interface IEvent {
void trigger();
}
public class PlayerEvent implements IEvent {
private Player player;
public void passPlayer(Player player){
this.player = player;
}
public void trigger(){
// player does things
}
}
public class BlockEvent implements IEvent {
private Block block;
public void passBlock(Block block){
this.block = block;
}
public void trigger(){
// block does things
}
}
但是,由于每个事件都依赖于一个Player或Block,具体取决于它的类型,我将不得不遍历列表并使用instanceof向下传播每个对象以传递相关的依赖项。
public void executeEvents(){
for(IEvent event : events){
if(event instanceof PlayerEvent){
((PlayerEvent) event).passPlayer(player);
} else {
((BlockEvent) event).passBlock(block);
}
event.trigger();
}
}
我读到在任何情况下都不应该进行向下转换,所以我一直想知道我可以使用哪些替代方案会遵循类似的简单执行路径但是属于良好的OOP实践?或者我应该完全取消接口并为每种事件类型分别列出一个列表?
答案 0 :(得分:0)
我读到在任何情况下都不应该进行向下转型, 所以我一直想知道有哪些替代方案
我不会概括。生成代码或使用反射的应用程序/库通常可以使用向下转换 在其他情况下,确实应该避免贬低。
您可以通过多种方式实现目标,而无需向下转发。
1)不要在列表中操纵过于宽泛的类型。此外,您可以将IEvent
作为通用界面,并在passPlayer()
中概括您将在界面中向上移动的passBlock()
和pass()
。
界面可能如下所示:
public interface IEvent<T> {
void trigger();
void pass(T t);
}
它的实现可能如下:
public class PlayerEvent implements IEvent<Player> {
private Player player;
public void trigger() {
// player does things
}
@Override
public void pass(Player t) {
}
}
现在使用更具体的类型列表,您可以写:
private Player player = ...;
public void executeEvents() {
List<IEvent<Player>> events = ...;
for (IEvent<Player> event : events) {
event.pass(player);
}
}
2)使用访客模式从双重调度中受益。
活动 - &gt;访客 - &gt;处理
每个pass()
方法都成为访问者的一种方法
您可以丰富IEvent
界面以添加接受accept()
的{{1}}方法:
Visitor
这里是访问者界面和实现:
访客界面
public interface IEvent {
void trigger();
void accept(Visitor visitor);
}
访客实施
public interface Visitor {
void visitBlockEvent(BlockEvent block);
void visitPlayerEvent(PlayerEvent player);
}
public class ProcessEventVisitor implements Visitor {
private Player player;
private Block block;
@Override
public void visitBlockEvent(BlockEvent blockEvent) {
// do your processing
}
@Override
public void visitPlayerEvent(PlayerEvent playerEvent) {
// do your processing
}
}
子类现在委托给Visitor参数处理:
IEvent
客户端代码现在看起来像:
public class PlayerEvent implements IEvent{
public void trigger() {
// player does things
}
@Override
public void accept(Visitor visitor) {
visitor.visitPlayerEvent(this);
}
}