Попытка реализовать шаблон посетителя - PullRequest
4 голосов
/ 13 декабря 2011

Я пытаюсь разобраться с методом посетителя в Java.

Я пытаюсь написать очень простую программу, чтобы привыкнуть к ней.В основном это меню еды.Я хочу прочитать в пользовательском вводе (тип еды (закуска, основное блюдо ...) и название еды (макароны, рыба ...)), а затем добавить этот пункт в меню.

IДо сих пор я уверен, что у меня правильный код, я просто пытаюсь понять, как передать значения, прочитанные пользователем.

Один из моих друзей, который также является программистом, сказал мне, что выдолжны иметь все ваши функциональные возможности в классах посетителей (или, по крайней мере, насколько это возможно).

Итак, я беру ввод пользователя и создаю его в элемент меню?Затем посетитель может добавить элемент в меню?(Я также хочу иметь возможность удалять элементы из меню, но я предполагаю, что это просто обратный инжиниринг метода добавления)

Или я не захожу так далеко, чтобы посетитель фактически добавилэлемент.Например;я просто создал бы элемент меню и затем передал бы его, затем имел бы функцию добавления в классе Menu?

Для меня было бы разумно, чтобы посетитель фактически добавил элемент, так как это функциональность, которую я хочуБудьте внимательны к добавляемому посетителю, но каждый раз, когда я пытаюсь реализовать, мне постоянно говорят, что я должен сделать массив, содержащий элементы меню, статичным, и я не могу не думать, что делаю это неправильно.

Я не уверен на 100%, что шаблон посетителя является правильным для того, что я пытаюсь сделать?

Лично я считаю, что я действительно очень близок ..... или ПУТЬOFF !!

Любая помощь, которую вы, ребята, можете предложить, была бы полезна, даже если вы можете указать мне хороший учебник, который поможет объяснить, как правильно использовать этот шаблон.

Вот что я имею до сих пор:

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

Ответы [ 2 ]

2 голосов
/ 26 декабря 2011

Я думаю, что ваш "добавляющий" посетитель не должен знать о том факте, что вы используете аргументы командной строки для указания имен вашего меню.

Действительно, это нарушает SRP => Принцип единой ответственности, потому что добавление и чтение - это два действия, а значит две обязанности. Чтобы понять это, представьте, что вы решили прочитать имена меню из файла ... вам придется открыть и перекодировать ваш класс «добавочного» посетителя.

У вас должен быть основной универсальный класс, который просто знает о String (для имен), и специализированный класс, который кто-то может создать или в конечном итоге использовать ваш, чтобы точно определить, откуда предоставляются аргументы.

Итак, в вашем примере вы должны попытаться заменить Console.readInt (); и Console.readString () с параметром метода int и параметром метода String.

0 голосов
/ 26 декабря 2011

В этом случае вам может не понадобиться резистор. gang-of-four говорит:

"... Использовать шаблон Visitor, когда

  • структура объекта содержит много классовобъектов с различными интерфейсами, и вы хотите выполнять операции над этими объектами, которые зависят от их конкретных классов.

  • необходимо выполнить множество различных и не связанных операций над объектами в структуре объекта,и вы хотите избежать "загрязнения" их классов этими операциями. Visitor позволяет объединять связанные операции, определяя их в одном классе. Когда структура объектов используется многими приложениями, используйте Visitor, чтобы поместить операции только в те приложения, которые в них нуждаются..

  • классы, определяющие структуру объекта, редко меняются, но вам часто требуется определять новые операции над структурой. Изменение классов структуры объекта требует переопределения интерфейса для всех посетителей, что потенциальнодорого. Если классы структуры объекта часто меняются, товероятно, лучше определить операции в этих классах.... "

Если вам действительно нужен шаблон посетителя для чего-то подобного, см. этот ответ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...