尝试实现访客模式

发布于 2024-12-21 08:44:41 字数 3691 浏览 3 评论 0原文

我正在尝试掌握 Java 中的访问者方法。

我正在尝试编写一个非常简单的程序来适应它。基本上它是一个食物菜单。我想读取用户输入(食物类型(开胃菜、主菜...)和食物名称(面食、鱼...)),然后将此项目添加到菜单中。

到目前为止,我相当确定代码是正确的,我只是在努力弄清楚如何传递从用户读取的值。

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

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

或者我不会让访问者实际添加元素。例如;我是否只需创建菜单元素,然后传递它,然后在菜单类中添加添加功能?

对我来说,让访问者实际添加项目是有意义的,因为它是我想保留特定于添加访问者的功能,但每次我尝试实现时,我总是被告知我必须制作包含菜单的数组列表元素是静态的,我忍不住认为我做错了。

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

I'm trying to get to grips with the visitor method in Java.

I'm trying to write a very simple program to get used to it. Basically it is a Food Menu. I want to read in user input (food type (starter, main course...) and the name of the food (pasta, fish...)) and then add this item to the menu.

I'm fairly sure I have the code correct so far, I'm just struggling to figure out how I pass the values read in from the user.

One of my friends who is also a programmer told me that you are supposed to have all of your functionality in the visitor classes (or at least as much as possible).

So do I take the user input and create it into a Menu Element? Then have the visitor add the element to the Menu? (I also want to be able to remove items from the Menu but I'm assuming that this is just reverse engineering the method to add)

Or do I not go so far as to have the visitor actually add the element. For example; would I just create the Menu Element and then pass that, then have the adding functionality in the Menu class?

To me it would make sense to have the visitor actually add the item, as it is functionality I want to keep specific to the adding visitor, but every time I try to implement I keep getting told that I have to make the arraylist containing the Menu Elements static, and I can't help but think I am doing it wrong.

I'm not 100% sure that the Visitor Pattern is correct for what I am trying to do?

Personally I believe I am either really, really close..... or WAY OFF!!

Any help you guys can offer would be great, even if you can point me towards a good tutorial that will help explain how to correctly use this pattern.

Here is what I have so far:

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

Menu Element Classes

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

The Menu Class

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

Visitor to Add Items to the Menu

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

Visitor to Remove Items from the Menu

class MenuElementRemoveVisitor implements MenuElementVisitor {

}

Run the code demo

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

友谊不毕业 2024-12-28 08:44:41

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

事实上,这打破了 SRP =>单一职责原则,因为添加和读取是两个操作,因此有两个职责。要理解这一点,假设您决定现在从文件中读取菜单名称...您必须打开并重新编码“添加”访问者类。

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

因此,在您的示例中,您应该尝试替换 Console.readInt();和 Console.readString() ,带有一个 int 方法参数和一个 String 方法参数。

I think that your "adding" visitor shouldn't know about the fact that you use Command-Line arguments to indicate your menu names.

Indeed, this breaks SRP => Single Responsibility Principle because adding and reading are two actions so two responsibilities. To understand that, imagine you decide to read menu names now from file ... you'll have to open and recode your "adding" visitor class.

You should have a main generic class who just know about String (for the names) and specialized class someone can create or eventually use yours to precise from where arguments are provided.

So in your example, you should try to replace Console.readInt(); and Console.readString() with an int method parameter and a String method parameter.

揪着可爱 2024-12-28 08:44:41

在这种情况下,您可能不需要访客。 四人帮 说:

" ...使用访问者模式

  • 对象结构包含许多具有不同接口的对象类,并且您希望对这些对象执行依赖于其具体类的操作。

  • 需要对对象结构中的对象执行许多不同且不相关的操作,并且您希望避免这些操作“污染”它们的类。 Visitor 允许您通过将相关操作定义在一个类中来将它们保留在一起。当对象结构被许多应用程序共享时,使用 Visitor 将操作仅放在需要它们的应用程序中。

  • 定义对象结构的类很少改变,但您经常希望在该结构上定义新的操作。更改对象结构类需要重新定义所有访问者的接口,这可能成本高昂。如果对象结构类经常更改,那么最好在这些类中定义操作。 ...”

如果您确实想要类似的访问者模式,请参阅此 答案。

You may not have a need for a vistor in this case. The gang-of-four says:

" ... Use the Visitor pattern when

  • an object structure contains many classes of objects with differing interfaces, and you want to perform operations on these objects that depend on their concrete classes.

  • many distinct and unrelated operations need to be performed on objects in an object structure, and you want to avoid "polluting" their classes with these operations. Visitor lets you keep related operations together by defining them in one class. When the object structure is shared by many applications, use Visitor to put operations in just those applications that need them.

  • the classes defining the object structure rarely change, but you often want to define new operations over the structure. Changing the object structure classes requires redefining the interface to all visitors, which is potentially costly. If the object structure classes change often, then it's probably better to define the operations in those classes. ..."

If you really want a visitor pattern for something similar see this answer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文