Посетитель возвращает первый элемент списка как нулевой - PullRequest
0 голосов
/ 11 июня 2018

Я хочу реализовать Visitor for My class MyList.Сам список содержит элементы типа MyEntry.Эти записи содержат общее значение и ссылку на следующую запись в списке.

public class MyEntry<E> implements Visitable {

    MyEntry<E> next;
    E o;

    MyEntry() {
       this(null, null);
    }

    MyEntry(E o) {
      this(o, null);
    }

    MyEntry(E o, MyEntry<E> e) {
     this.o = o;
     this.next = e;
    }

    public void accept(Visitor visitor) {
    }
}

Класс списка

public class MyList<E> implements Visitable {

 private MyEntry<E> begin;

 private MyEntry<E> pos;


 public MyList() {
   pos = begin = new MyEntry<E>();
 }


 public void add(E x) {
   MyEntry<E> newone = new MyEntry<E>(x, pos.next);

   pos.next = newone;
 }


 public void advance() {
    if (endpos()) {
       throw new NoSuchElementException("Already at the end of this List");
    }
    pos = pos.next;
 }


 public void delete() {
    if (endpos()) {
       throw new NoSuchElementException("Already at the end of this List");
    }
    pos.next = pos.next.next;
 }


 public E elem() {
    if (endpos()) {
       throw new NoSuchElementException("Already at the end of this List");
    }     
    return pos.next.o;
 }


 public boolean empty() {
    return begin.next == null;
 }


 public boolean endpos() { 
    return pos.next == null;
 }

 public void reset() {
    pos = begin;
 }

  @Override
  public void accept(Visitor visitor) {

      begin = pos;

      while(pos.next != null && visitor.visit(pos.o)) {
          //Move one Item forward
          pos = pos.next;

     }
}

Я реализовал интерфейс Visitor для моего ListVisitor класса

public class ListVisitor implements Visitor {

  public ListVisitor() {
      }

  @Override
  public boolean visit(Object o) {
      return false;
  }
}

Интерфейс Visitor, которыйбудет реализован в каждом новом посетителе, которого я хочу создать, пока у меня есть только ListVisitor

public interface Visitor<E> { 
   boolean visit(Object o);
}

и интерфейс Visitable, который реализован в каждом классе, который я хочу посетить, в этом случаекласс MyList и класс MyEntry.

public interface Visitable {
    public void accept(Visitor visitor);
}

Чтобы протестировать реализацию шаблона Visitor, я создал Testclass, который создает новый Mylist и помещает в него несколько строк.Затем он создает нового посетителя, который посещает список.

import org.junit.Test;

public class MyListTest {

  @Test
  public void MyListTest() {

      MyList s = new MyList();


     s.add("Hello");
     s.add("World");
     s.add("!");

      Visitor v = new Visitor() {

          @Override
          public boolean visit(Object o) {
            System.out.println(o);
            return true;
          }
      };
      s.accept(v);
   }
}

Теперь, когда я запускаю MyListTest, вывод будет:
null
!
World

Мой вопрос теперь, почему первый Элемент, который посетительпосещения имеет нулевую ссылку в нем.Когда я добавляю больше элементов в свой список перед созданием посетителя, вывод всегда расширяется, за исключением первого элемента, который был вставлен в список, он всегда будет нулевым.

1 Ответ

0 голосов
/ 20 сентября 2018

Шаблон посетителя не изменит текущую структуру кода.Он используется для добавления новой функциональности в существующий код.Классы, которые содержат новые поведения, обычно известны как Посетители.

Классы и объекты, участвующие в этом шаблоне:

Посетитель : Он объявляет операцию посещения для каждого класса ConcreteElement в структуре объекта.Имя и подпись операции идентифицируют класс.

ConcreteVisitor : он реализует каждую операцию, объявленную посетителем.

элемент : он определяет принятиеоперация, которая принимает посетителя в качестве аргумента.

ConcreteElement : она реализует операцию Accept, которая принимает посетителя в качестве аргумента.

ObjectStructure :Он содержит все элементы структуры данных как коллекцию, список чего-то, что может быть перечислено и использовано посетителями.

public abstract class Food {

    public final string Name {
        get {}
        set {}
    }

    public final Decimal Price {
        get {}
        set {}
    }

    public final int Count {
        get {}
        set {}
    }

    public Food(string name, Decimal price, int count) {
        this.Name = name;
        this.Price = price;
        this.Count = count;
    }

    public abstract void Accept(Visitor visitor);
}

public class Pizza extends Food {

    public Pizza(string name, Decimal price, int count) {
        super(name, price, count);
    }

    public override void Accept(Visitor visitor) {
        visitor.Visit(this);
    }
}

public class Pasta extends Food {

    public Pasta(string name, Decimal price, int count) {
        super(name, price, count);
    }

    public override void Accept(Visitor visitor) {
        visitor.Visit(this);
    }
}

public abstract class Visitor {

    public abstract void Visit(Pasta pasta);
    public abstract void Visit(Pizza pizza);

}

public class DiscountVisitor extends Visitor {

    public override void Visit(Pasta pasta) {
        var totalPrice = (pasta.Price * pasta.Count);
        byte discount = 10;
        pasta.Price = (totalPrice - (totalPrice * (discount / 100)));
    }

    public override void Visit(Pizza pizza) {
        byte discount = 0;
        if ((pizza.Count < 5)) {
            discount = 10;
        }
        else if (((pizza.Count >= 5) && (pizza.Count < 20))) {
            discount = 20;
        }
        else {
            discount = 30;
        }

        var totalPrice = (pizza.Price * pizza.Count);
        pizza.Price = (totalPrice - (totalPrice * (discount / 100)));
    }
}

public class OrderList extends List<Food> {

     public final void Attach(Food element) {
        Add(element);
    }

    public final void Dettach(Food element) {
        Remove(element);
    }

    public final void Accept(Visitor visitor) {
        this.ForEach(() => {  }, x.Accept(visitor));
    }

    public final void PrintBill() {
        this.ForEach(() => {  }, this.Print(x));
    }

    private final void Print(Food food) {
        Console.WriteLine(string.Format("FoodName: {0}, Price:{1}, Count:{2}", food.Name, food.Price, food.Count));
    }
}

}

OrderList orders = new OrderList();
orders.Add(new Pizza("pizza", 45000, 2));
orders.Add(new Pasta("pasta", 30000, 1));

DiscountVisitor visitor = new DiscountVisitor();

orders.Accept(visitor);

orders.PrintBill();
...