2016-01-22 86 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

這是一個不錯的主意,但我認爲它可能稍微不靈活(我必須爲每個操作分配一些特定的實現,其中有很多類型。)另外,我擔心任何長期存在的引用將堅持在很少使用的電話。 –