java – 尝试实现访问者模式

我正试图掌握
Java中的访问者方法.

我正在尝试编写一个非常简单的程序来习惯它.基本上它是一个美食菜单.我想阅读用户输入(食物类型(入门,主菜……)和食物名称(意大利面,鱼……)),然后将此项添加到菜单中.

我很确定到目前为止我的代码是正确的,我只是想弄清楚如何传递用户读入的值.

我的一位同时也是程序员的朋友告诉我,你应该在访问者类中拥有所有功能(或者至少尽可能多).

那么我是否将用户输入创建为菜单元素?然后让访问者将元素添加到菜单中? (我也希望能够从菜单中删除项目,但我假设这只是对要添加的方法进行逆向工程)

或者我没有让访问者真正添加元素.例如;我只是创建菜单元素,然后传递,然后在菜单类中添加功能?

对我来说,让访问者实际添加项目是有意义的,因为它是我想要保持特定于添加访问者的功能,但每次我尝试实现时我都会被告知我必须使包含菜单的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);
    }
}

菜单类

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());
    }
}

最佳答案 我认为您的“添加”访问者不应该知道您使用命令行参数来指示菜单名称的事实.

实际上,这打破了SRP =>单一责任原则因为添加和阅读是两个行为所以两个责任.要理解这一点,想象一下你现在决定从文件中读取菜单名称……你必须打开并重新编码你的“添加”访问者类.

你应该有一个主要的泛型类,它只知道String(用于名称)和专门的类,有人可以创建或最终使用你的类来精确地提供参数.

所以在你的例子中,你应该尝试替换Console.readInt();和带有int方法参数和String方法参数的Console.readString().

点赞