2011-12-13 100 views
4

我試圖去掌握Java中的訪問者方法。試圖實現訪問者模式

我想寫一個非常簡單的程序來適應它。基本上它是一個食物菜單。我想讀取用戶輸入(食物類型(起動器,主菜...)和食物(麪食,魚...)的名稱),然後將此項目添加到菜單中。

我相當肯定我到目前爲止的代碼是正確的,我只是努力弄清楚如何傳遞從用戶讀取的值。

我的一位同時也是程序員的朋友告訴我,你應該在訪問者類中(或者至少儘可能)擁有所有的功能。

那麼,我需要用戶輸入並將其創建爲菜單元素?然後讓訪問者將該元素添加到菜單中? (我也希望能夠從菜單中刪除項目,但我假設這只是逆向工程的方法來添加)

或者我不會讓訪問者實際添加元素。例如;我是否會創建菜單元素,然後傳遞它,然後在Menu類中添加功能?

對我來說,讓訪問者真正添加項目是有意義的,因爲它是我想保持特定於添加訪問者的功能,但是每次我嘗試實現時,都會被告知我必須使包含菜單元素靜態的arraylist,我不禁想到我做錯了。

我不是100%確定訪客模式對於我正在嘗試執行的操作是否正確?

就我個人而言,我相信我是真的,真的很接近.....或者不要走!

任何幫助你們可以提供的將是很好的,即使你可以指向我一個很好的教程,這將有助於解釋如何正確使用這種模式。

這是我到目前爲止有:

interface MenuElementVisitor { 
    void visit(Starter starter); 
    void visit(MainCourse mainCourse); 
    void visit(Desert desert); 
    void visit(Drinks drinks); 
    void visit(Menu menu); 
} 

菜單元素類

interface MenuElement { 
    void accept(MenuElementVisitor visitor); // MenuElements have to provide accept(). 
} 

class Starter implements MenuElement { 
    private String name; 

    public Starter(String name) { 
     this.name = name; 
    } 

    public String getName() { 
     return this.name; 
    } 

    public void accept(MenuElementVisitor visitor) { 
     visitor.visit(this); 
    } 
} 

class MainCourse implements MenuElement { 
    private String name; 

    public MainCourse(String name) { 
     this.name = name; 
    } 

    public String getName() { 
     return this.name; 
    } 

    public void accept(MenuElementVisitor visitor) { 
     visitor.visit(this); 
    } 
} 

class Desert implements MenuElement { 
    private String name; 

    public Desert(String name) { 
     this.name = name; 
    } 

    public String getName() { 
     return this.name; 
    } 

    public void accept(MenuElementVisitor visitor) { 
     visitor.visit(this); 
    } 
} 

class Drinks implements MenuElement { 
    private String name; 

    public Drinks(String name) { 
     this.name = name; 
    } 

    public String getName() { 
     return this.name; 
    } 

    public void accept(MenuElementVisitor visitor) { 
     visitor.visit(this); 
    } 
} 

Menu類

class Menu implements MenuElement { 
    MenuElement[] elements; 

    public MenuElement[] getElements() { 
     return elements.clone(); // Return a copy of the array of references. 
    } 

    public Menu() { 
     this.elements = new MenuElement[] {  
      new Starter("Soup"), 
      new Starter("Pate"), 
      new MainCourse("Steak"), 
      new MainCourse("Fish"), 
      new Desert("Ice Cream"), 
      new Desert("Apple Tart"), 
      new Drinks("7up"), 
      new Drinks("Wine"), 
     }; 
    } 

    public void accept(MenuElementVisitor visitor) { 
     for(MenuElement element : this.getElements()) { 
      element.accept(visitor); 
     } 
     visitor.visit(this);  
    } 
} 

遊客將項目添加到菜單

class MenuElementAddVisitor implements MenuElementVisitor { 
    System.out.println("Press 1 for Starter, 2 for Main Course, 3 for Desert or 4 for Drinks"); 
    int MenuElementType = Console.readInt(); 
    System.out.println("Type the name of the Menu Element you want to add"); 
    String MenuElementName = Console.readString(); 

觀衆從菜單

class MenuElementRemoveVisitor implements MenuElementVisitor { 

} 

刪除項目運行代碼演示

public class VisitorDemo { 
    static public void main(String[] args) { 
     Menu menu = new Menu(); 
     menu.accept(new MenuElementAddVisitor()); 
     menu.accept(new MenuElementRemoveVisitor()); 
    } 
} 
+2

看起來既訪問者類並沒有使其在。無論有訪問方法和第二個是空的 –

+0

該死的!我忘了在昨天晚上(我發佈帖子的時候很晚了,我現在要扔掉我現在的代碼) – Ian

回答

2

我認爲你的「並稱」不訪問者應該知道你使用命令行參數的事實以表明你的菜單名稱。

事實上,這打破了SRP =>單一責任原則,因爲添加和閱讀是兩個動作,所以兩個責任。要理解這一點,想象你現在決定從文件中讀取菜單名稱......你必須打開並重新編碼你的「添加」訪問者類。

您應該擁有一個主要的泛型類,他們只知道String(用於名稱)和專門的類,他們可以創建或最終使用您的參數提供的精確位置。因此在你的例子中,你應該嘗試替換Console.readInt();和Console.readString()與一個int方法參數和一個String方法參數。

+0

根據我的說法,在一個已經創建的對象上,而不是添加它...我會用一個靜態方法來替換您的MenuElementAddVisitor Factory,其中包含一個String和一個Int參數,例如。 – Mik378

+0

對不起,但你的評論很不清楚。編寫一個處理對象層次結構的訪問者並將其他對象添加到其他對象中沒有任何問題。事實上,我們甚至不知道OP的意圖是什麼,因爲他的訪問者課程不完整。 –

0

在這種情況下,您可能不需要訪客。該gang-of-four說:

「......當

  • 對象結構包含很多類對象的具有不同接口的使用訪問者模式,你想對這些對象依賴於執行操作它們的具體類

  • 需要在對象結構中的對象上執行許多獨特和不相關的操作,並且希望避免使用這些操作「污染」它們的類。在一個類中定義它們。當對象結構被許多應用程序共享時,使用Visitor將操作放在那些需要它們的應用程序中。

  • 定義對象結構的類幾乎不會改變,但您通常希望在結構上定義新的操作。更改對象結構類需要重新定義所有訪問者的接口,這可能是昂貴的。如果對象結構類經常變化,那麼定義這些類中的操作可能會更好。 ......」

如果你真的想類似的東西,一個訪問者模式看this答案。