私はグラフの実装に取り組んでいます。私の Graph クラスは次のようになります。
public class Graph<VERTEX_TYPE, EDGE_TYPE, IDENTIFIER_TYPE>
where VERTEX_TYPE : Identifier<IDENTIFIER_TYPE>
where EDGE_TYPE : Identifier<IDENTIFIER_TYPE>
where IDENTIFIER_TYPE : IConvertible
{
...
}
(実装されたインターフェースは気にしないでください。質問には関係ありません)。
Vertex クラスと Edge クラスの両方に、次の方法でアクセスできる一般的なデータが含まれています。
public class Vertex<VERTEX_TYPE,EDGE_TYPE,IDENTIFIER_TYPE>
where VERTEX_TYPE : Identifier<IDENTIFIER_TYPE>
where EDGE_TYPE : Identifier<IDENTIFIER_TYPE>
{
public VERTEX_TYPE Data{get;private set;}
....
}
public class Edge<EDGE_TYPE,VERTEX_TYPE,IDENTIFIER_TYPE>
where EDGE_TYPE : Identifier<IDENTIFIER_TYPE>
where VERTEX_TYPE : Identifier<IDENTIFIER_TYPE>
{
public EDGE_TYPE Data{get;private set;}
....
}
これで、いくつかのアルゴリズムを実装する GraphVisitor クラスができました。グラフがトラバースされるとき、アルゴリズムによって現在トラバースされているエッジと頂点の両方でいくつかのデリゲートが呼び出されるようにします。
2 組のデリゲートを定義しました。1 組は、 などのグラフ要素で実行する必要がある操作に関連していますVertex<VERTEX_TYPE,EDGE_TYPE,IDENTIFIER_TYPE>
。デリゲートの 2 番目のペアは、保持されているデータに対してのみ実行された操作に関連しています。
public class GraphVisitor<VERTEX_TYPE, EDGE_TYPE, IDENTIFIER_TYPE>
where VERTEX_TYPE : Identifier<IDENTIFIER_TYPE>
where EDGE_TYPE : Identifier<IDENTIFIER_TYPE>
where IDENTIFIER_TYPE : IConvertible
{
public delegate void VertexDataOperation(VERTEX_TYPE vertex);
public delegate void EdgeDataOperation(EDGE_TYPE vertex);
public delegate void VertexOperation(Vertex<VERTEX_TYPE,EDGE_TYPE,IDENTIFIER_TYPE> vertex);
public delegate void EdgeOperation(Edge<EDGE_TYPE,VERTEX_TYPE,IDENTIFIER_TYPE> vertex);
.....
}
BFS アルゴリズムを実装しました (実装全体を投稿することは避けます)。パラメーターとして 2 つのデリゲートを使用します。
public void BFS(VertexOperation op, EdgeOperation edgeOp)
{
...
Vertex<VERTEX_TYPE,EDGE_TYPE,IDENTIFIER_TYPE> currentVertex;
op(currentVertex);
foreach (Edge<EDGE_TYPE,VERTEX_TYPE,IDENTIFIER_TYPE> e in currentVertex.NeighBors())
{
edgeOp(e);
...
}
...
と の BFS バージョンを作成しようとVertexDataOperation
しEdgeDataOperation
ていましたが、2 つの異なるデリゲート パラメータ タイプを使用するには、最終的にすべての BFS コードをコピーする必要があることに気付きました。
public void BFS(VertexDataOperation op, EdgeDataOperation edgeOp)
...
Vertex<VERTEX_TYPE,EDGE_TYPE,IDENTIFIER_TYPE> currentVertex;
op(currentVertex.Data); //method differs only here
foreach (Edge<EDGE_TYPE,VERTEX_TYPE,IDENTIFIER_TYPE> e in currentVertex.NeighBors())
{
edgeOp(e.Data);//method differs only here
...
}
同じメソッドの同一の実装を避けたいと思います。変更されるのは、メソッド シグネチャと、メソッドが呼び出されるオブジェクトだけです。
このコードの設計を改善するためのアイデアはありますか?
編集:
4 つのデリゲートすべてを関数に渡すこともできますが、トラバーサルごとに 1 組しか使用しないため、あまりきれいに見えません。