为多对多和一对多关系实现逻辑类结构?

时间:2011-05-24 23:54:58

标签: c# oop

我有一组三个相互关联的类。具体来说,Shuttle,Stop和Route。

Stops can lie on multiple Routes and therefore Routes contain Stops.
Shuttles can exist on one Route at a time, but Routes can contain multiple Shuttles.
A Stop will always exist on at least one Route.
A Shuttle may exist on no Route (though this is avoidable by discarding any Shuttles that are off-Route).

我遇到的问题是如何逻辑地关联这三个类,以便尽可能简单地访问它们。

一个类的每个实例都有一个唯一的ID(在它自己的类型中)来引用,所以我将所有内容都存储在Dictionaries中,以便能够通过它的ID访问任何元素。

我开始使用的关系可以很容易地选择一个特定的路线,但因为路径和航天飞机包含在路线中的词典中。我必须知道什么路线停靠或班车正在引用它,这是不可能的,因为我只有一个可用的路线列表,所以有必要迭代每条路线,直到我找到正确的停车/班车。

我提出的每一个选择都会遇到类似的问题。我想出的最好的就是

class Container
{
    Dictionary<int, Shuttle> shuttles;
    Dictionary<int, Route> routes;
}

class Shuttle
{
    int shuttleId;
    int routeId;
}

class Route
{
    int routeId;
    Dictionary<string, Stop> stops;
}

class Stop
{
    string stopId;
}

但是,这只是最好的,因为此时代码的具体操作。它计算每个停靠/航线组合的ETA,这可以通过迭代航天飞机并计算该航天飞机到达当前航线的每个站点所需的时间来完成。

我还有其他地方想要使用这些类,例如在地图显示上。在那里,这个结构中断了,因为我希望在选择Stop时显示气球,显示Stop链接到的路径。显然我无法直接获取该信息,因为Stop不了解路由。

2 个答案:

答案 0 :(得分:2)

这是一种方法。实体之间的双向引用确实需要一些维护代码来管理更改,但您可以轻松地从任何实例转到任何其他实例。

// World knows about every entity in it.
// World cares not how entities are related to each other.
public class World
{
  Dictionary<int, Shuttle> shuttles;
  Dictionary<int, Route> routes;
  Dictionary<int, Stop> stops;
}

public class Shuttle
{
  Route CurrentRoute;
}

public class Stop
{
  Dictionary<int, Route> Routes;
}

public class Route
{
  Dictionary<int, Shuttle> Shuttles;
  Dictionary<int, Stop> Stops;
}

例如,所有班车都在一条路线上。

from stop in World.routes[myRouteId].Stops.Values
from route in stop.Routes.Values
where route.Id != myRouteId
from shuttle in route.Shuttles 
select shuttle;

答案 1 :(得分:1)

修改您的Container类,以提供获取给定停靠点的所有路径的方法。

public static class Container
{
    private static Dictionary<int, Shuttle> shuttles;
    private static Dictionary<int, Route> routes;

    /* Other stuff goes on to initialize shuttles and routes I  assume */

    public static List<Route> getRoutes(string stopId)
    {
        List<Route> stopRoutes = new List<Route>();

        foreach (int myKey in routes.Keys)
        {
             foreach (string str in routes[myKey].stops.Keys)
             {
                   if (routes[myKey].stops[str] == stopId)
                   {
                        stopRoutes.Add(routes[myKey]);
                        break;
                   }
             }
         }

         return stopRoutes;
      }

如果您正在使用非常大的数据集,或者您可能会频繁地进行此调用,那么您可能需要比上述更有效的方法。例如,您将getRoutes方法设为私有,并维护一个将stopIds映射到Route列表的字典,并在添加新路由或新站点时更新它,以防止每次需要停止路径时都需要调用getRoutes。

我还假设你的应用程序只需要一个Container类的一个实例,因为它似乎只是所有航天飞机/航线数据的容器。