访客将列表的第一个项目返回为空

时间:2018-06-10 21:08:53

标签: java list visitor visitor-pattern

我想为我的班级MyList实施一个访问者。 List本身包含MyEntry类型的元素。这些Entrys持有一个通用值和对列表中下一个条目的引用。

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

List类

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

Interface Visitable,在我想访问的每个类中实现,在本例中是MyList类和MyEntry类。

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

为了测试访问者模式的实现,我创建了一个Testclass,它创建了一个新的Mylist并在其中添加了一些字符串。接下来,它会创建一个访问List的新访问者。

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时,输出为:


世界

我的问题现在是访问者访问的第一个元素中包含空引用的原因。当我在创建访问者之前向我的列表中添加更多项目时,输出总是会扩展,除了插入到List中的第一个项目之外,它总是为空。

1 个答案:

答案 0 :(得分:0)

访问者模式不会更改当前代码结构。它用于在现有代码中添加新功能。具有新行为的类通常称为“访问者”。

参与此模式的类和对象是:

  

访问者:它为对象结构中的每个ConcreteElement类声明了一个Visit操作。操作名称和   签名识别类。

     

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