我想为我的班级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中的第一个项目之外,它总是为空。
答案 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();