gpt4 book ai didi

c# - 访客模式 : different ways to visit the same structure

转载 作者:行者123 更新时间:2023-11-30 22:00:52 24 4
gpt4 key购买 nike

我有这种表结构:

public class Table : IVisitable
{
public List<Row> rows;
public void accept(IVisitor visitor)
{
foreach(Row row in rows)
row.accept(visitor);
visitor.visit(this);
}
}

public class Row : IVisitable
{
public List<Cell> columns;
public void accept(IVisitor visitor)
{
foreach(Cell cell in columns)
cell.accept(visitor);
visitor.visit(this);
}
}
public class Cell : IVisitable
{
public void accept(IVisitor visitor)
{visitor.visit(this);}
}

解析器将创建此类的对象,所以我有点手忙脚乱地扩展类或类似的东西(但我可以在好的解决方案面前重新考虑)。

现在,如您所见,我实现了 accept() 方法访问整个表,但现在我想定义一个只访问前 2 个表的访问者表的行。我如何在不添加另一个 accept() 的情况下做到这一点?

更新:我考虑过这个解决方案,我想听听您的意见。在不重写上面的整个代码的情况下,假设每个类都没有实现 IVisitable 接口(interface)(因此每个类都没有 accept() )。创建两个扩展表的类怎么样?像这样:

public class VisitTwoRowTable : Table,IVisitable
{
public VisitTwoRowTable(Table table)
{
foreach(Row row in table.rows)
this.rows.add(row);
}
public void accept(IVisitor visitor)
{
for(int i=0;i<2;i++)
row[i].accept(visitor);
visitor.visit(this);
}
}

还有这个:

public class VisitWholeTable : Table,IVisitable
{
public VisitWholeTable(Table table)
{
foreach(Row row in table.rows)
this.rows.add(row);
}
public void accept(IVisitor visitor)
{
foreach(Row row in rows)
row.accept(visitor);
visitor.visit(this);
}
}

这个解决方案唯一真的很丑的地方是构造函数部分,它创建了一个副本(浅拷贝)

最佳答案

您可以简单地为您的访问者添加一个状态并跟踪您已经访问过的行数。

鉴于这些类型(为简洁起见,我省略了 Cell):

public interface IVisitor
{
void visit(Row v);
void visit(Table v);
}

public interface IVisitable
{
void accept(IVisitor visitor);
}

public class Table : IVisitable
{
public List<Row> rows;
public void accept(IVisitor visitor)
{
foreach(Row row in rows)
row.accept(visitor);
visitor.visit(this);
}
}

public class Row : IVisitable
{
public int number;
public void accept(IVisitor visitor)
{
visitor.visit(this);
}
}

您的访问者可能看起来像:

public class FirstTwoRowVisitor : IVisitor
{
int _numOfRows = 0;

public void visit(Row r)
{
if (_numOfRows == 2)
return;
Console.WriteLine("Visited Row #{0}", r.number);
_numOfRows++;
}

public void visit(Table t)
{
Console.WriteLine("Table has {0} Rows total", t.rows.Count);
}
}

示例:

var t = new Table() { rows = new List<Row>() };
int i = 0;
t.rows.Add(new Row() {number = i++});
t.rows.Add(new Row() {number = i++});
t.rows.Add(new Row() {number = i++});
t.rows.Add(new Row() {number = i++});
var v = new FirstTwoRowVisitor();
t.accept(v);

会输出

Visited Row #0
Visited Row #1
Table has 4 Rows total

(这当然只是一个简单的示例,每个实例只能处理两行;但您可以根据需要进行更改)


回应您的评论:

public interface IVisitor
{
void visit(Row v);
void visit(Table v);
bool keepgoing { get; }
}

public class Table : IVisitable
{
public List<Row> rows;
public void accept(IVisitor visitor)
{
foreach(Row row in rows)
if (visitor.keepgoing) row.accept(visitor);
else break;
visitor.visit(this);
}
}

public class FirstTwoRowVisitor : IVisitor
{
int _numOfRows = 0;

public bool keepgoing { get { return _numOfRows < 2; } }

public void visit(Row r)
{
if (!keepgoing)
return;
Console.WriteLine("Visited Row #{0}", r.number);
_numOfRows++;
}

public void visit(Table t)
{
Console.WriteLine("Table has {0} Rows total", t.rows.Count);
}
}

关于c# - 访客模式 : different ways to visit the same structure,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28212877/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com