我正在尝试掌握Java中的访问者方法。
我正在试着写一个非常简单的程序来适应它。基本上,它是一个食物菜单。我想读入用户输入(食物类型(开胃菜,主菜...)和食物的名称(意大利面,鱼...)然后将此项目添加到菜单中。
到目前为止,我确信我的代码是正确的,我只是在努力弄清楚如何传递从用户读取的值。
我的一个也是程序员的朋友告诉我,你应该在访问者类中拥有所有的功能(或者至少是尽可能多的)。
那么,我是否需要将用户输入创建到一个菜单元素中呢?然后让访问者将元素添加到菜单中?(我也希望能够从菜单中删除菜单项,但我假设这只是对要添加的方法进行反向工程)
或者我还没有走到让访问者实际添加元素的地步。例如,我是否只需要创建Menu元素,然后传递它,然后在Menu类中添加功能?
对我来说,让访问者实际添加项目是有意义的,因为这是我想要保留的特定于添加访问者的功能,但每次我尝试实现时,我总是被告知必须使包含菜单元素的arraylist成为静态的,我不禁认为我这样做是错误的。
我不是百分之百确定访问者模式对于我正在尝试做的事情是正确的?
就我个人而言,我相信我要么真的,真的很接近.否则就太离谱了!
你们能提供的任何帮助都是很棒的,即使你能给我一个好的教程来帮助我解释如何正确地使用这个模式。
这是我到目前为止所知道的:
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());
}
}发布于 2011-12-26 04:02:15
我认为您的“添加”访问者不应该知道您使用命令行参数来指示菜单名称的事实。
事实上,这打破了SRP =>的单一责任原则,因为添加和读取是两个动作,所以是两个责任。为了理解这一点,假设您现在决定从文件中读取菜单名称...你必须打开并重新编码你的“添加”访问者类。
您应该有一个只知道String (用于名称)的主要泛型类,以及一些人可以创建或最终使用您的类来精确地提供参数的专用类。
因此,在您的示例中,您应该尝试将Console.readInt();和Console.readString()替换为一个整数方法参数和一个字符串方法参数。
发布于 2011-12-26 06:59:55
在这种情况下,您可能不需要访问者。gang-of-four说:
“...在以下情况下使用访问者模式
如果你真的想要一个类似的访问者模式,参见this answer。
https://stackoverflow.com/questions/8482734
复制相似问题