尝试实现访客模式
我正在尝试掌握 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我认为您的“添加”访问者不应该知道您使用命令行参数来指示菜单名称的事实。
事实上,这打破了 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.
在这种情况下,您可能不需要访客。 四人帮 说:
如果您确实想要类似的访问者模式,请参阅此 答案。
You may not have a need for a vistor in this case. The gang-of-four says:
If you really want a visitor pattern for something similar see this answer.