2016-01-22 63 views
1

声音令人毛骨悚然,呵呵...匿名访客

我正在开发一个GUI驱动的应用程序,它使用了大量的访问者模式的。我采取了这种方法,因为对于我来说,处理一些特定于类的图形元素非常重要,尽管这些类本身需要充当简单的数据对象。在这方面,他们完全不知道他们在我的应用程序逻辑中受到的多种场景。

我对这个设计选择的问题是,随着我的应用程序的增长,我发现自己被迫为anonymous Visitor实现进行常量运行时分配,以便在方法体中描述我的类特定的代码。由于其中许多依赖于通话时提供的参数,因此我无法将其中的很多提取到可重用的static实现中。

下面是一个示例,使用在运行时传递的Shaker对象仅对Button类型执行操作。

private abstract class Graphical implements Visitor.Dispatch { 
    /* Position. */ 
    private int X; 
    private int Y; 
}; 

private final class Button extends Graphical { 
    @Override public final void onVisit(final Visitor pVisitor) { pVisitor.onReceived(this); } }; 

private final class ScrollBar extends Graphical { 
    @Override public final void onVisit(final Visitor pVisitor) { pVisitor.onReceived(this); } 
}; 

public static interface Visitor { 
    /* Adapter. */ 
    public static class Adapter implements Visitor { 
     @Override public void onReceived( Button pButton) { } 
     @Override public void onReceived(ScrollBar pScrollBar) { } 
    }; 
    /* Dispatch Method. */ 
    public static interface Dispatch { 
     public abstract void onVisit(final Visitor pVisitor); 
    }; 
    /* Visitor Implementations. */ 
    public abstract void onReceived(final Button pButton); 
    public abstract void onReceived(final ScrollBar pScrollBar); 
}; 

/* Iterates through a List of Graphicals and Shakes a Button. */ 
public static void onShakeButtons(final List<Graphical> pGraphicals, final Shaker pShaker) { 
    /* Allocate a Visitor. */ 
    final Visitor.Adapter lVisitor = new Visitor.Adapter() { @Override public void onReceived(final Button pButton) { 
     /* Shake the Button! */ 
     pShaker.onShake(pButton); 
    } }; 
    /* Iterate the Graphicals. */ 
    for(final Graphical lGraphical : pGraphicals) { lGraphical.onVisit(lVisitor); } 
} 

任何人都可以建议如何减少我分配的数量吗?或者我对这种模式如何应用有一个真正的误解?

+0

你能展示一个有代表性的代码示例吗? – Fildor

+0

创建对象有什么问题? Java是一个OO对象。创建对象是正常的,预期的和快速的。有没有一个具体的问题? –

+0

如果您使用匿名访问者很多,您应该考虑在Java 8中使用lambda表达式,因为这些往往更简单,更清晰。 –

回答

1

有一个选项。 您可以在您的访客内为您的非静态对象创建容器,并使用新的非静态对象更新这些容器并重新使用访问者。

public class ConcreteVisitor extends Visitor { 

     private final AtomicReference<MyClass> mValue_1 = new AtomicReference<MyClass>(); 

     private final AtomicReference<SomeClass> mValue_2 = new AtomicReference<SomeClass>(); 

     public void updateVisitor(MyClass newMyClass, SomeClass newSomeClass) { 
      mValue_1.set(newMyClass) 
      mValue_2.set(newSomeClass) 
     } 

     @Override 
     public void visitElement_1(Element_1 element) { 
      // use your updated values here 
     } 

     @Override 
     public void visitElement_2(Element_2 element) { 
      // use your updated values here 
     } 
    } 

当你需要重用访问者,您只需更新的值,然后再运行它:

// You create it only once: 
    Visitor concreteVisitor = new ConcreteVisitor(); 

    // and reuse it all the time 
    concreteVisitor.updateVisitor(newMyClass, newSomeClass); 
    concreteVisitor.visitElement(element); 

我用的AtomicReference容器,但可以使用自定义容器类。

+0

这是一个不错的主意,但我认为它可能稍微不灵活(我必须为每个操作分配一些特定的实现,其中有很多类型。)另外,我担心任何长期存在的引用将坚持在很少使用的电话。 –