【发布时间】:2020-04-21 16:59:12
【问题描述】:
我有一个问题必须通过我不知道的设计模式来解决。这是用于不同坐标系之间的转换。我给你解释。
1/ 我有一个引用系统集合 (EPSG) 的枚举:
public enum System
{
NAD27 = 3800,
NAD83 = 3801,
...
WGS84 = 4326
}
这些枚举允许定义对象坐标使用的系统。
public struct Coordinate
{
public System system;
public double X;
public double Y;
public double Z;
}
可以有无数个系统。枚举索引不一定相互跟随,也不能修改。
2/ 对象必须能够从一个系统传递到另一个系统。我将转换从一个系统应用到另一个系统。系统 A -> 系统 B。 此转换不会更改类型。它会更改坐标(x、y 和 z)的值,以便该点根据其系统位于正确的位置。
所有组合都是可能的。但是,根据启动系统的不同,改变系统的计算并不总是相同的。
3/ 我有几个包含转换方法的静态类:
public static class WGS84
{
public static Coordinate ToNAD27 (double X, double Y, double Z)
{
...
}
public static Coordinate ToNAD83 (double X, double Y, double Z)
{
...
}
}
我们来解决问题。
4/ 如果我第一次使用一个开关,将包含起始系统和到达系统的对象作为参数,则定义使用哪种转换并避免大量转换:
public class SystemTransform
{
public System initial;
public System terminal;
}
public struct Coordinate
{
public System system;
public double X;
public double Y;
public double Z;
public Coordinate Transform (SystemTransform s)
{
switch(s)
{
case SystemTransform st when st.Initial == System.WGS84 && st.Terminal == System.NAD27:
return WGS84.ToNAD27(X, Y, Z);
...
case SystemTransform st when st.Initial == System.WGS84 && st.Terminal == System.Z:
throw new NotImplementedException ($ "{s} not implmented");
}
}
}
5/ 不切实际和审美,我翻了字典:
public static class TransformWithDictionary
{
private static Dictionary <SystemTransform, Func <Coordinate , Coordinate >> ParserMap = new Dictionary <SystemTransform, Func <Coordinate , Coordinate >>
{
{new SystemTransform (System.WGS84, System.NAD27), coord => WGS84.ToNAD27(coord)},
{new SystemTransform (System.WGS84, System.NAD83), coord => WGS84.ToNAD83(coord)},
};
public MyObject GetParserFor (SystemTransform st, Coordinate coord)
{
if (! ParserMap.ContainsKey(st))
throw new NotImplementedException ("Unexpected file type value" + st);
return ParserMap[st](coord);
}
}
它更优雅一点,但这并不能解决问题。
理论上,我面临着一个有∞可能性的开关。可以说,无法手动填充并随着时间的推移对其进行维护。
第三个想法是制造工厂。但这无助于我根据来源系统和到达系统来定义使用哪个函数。
有解决这个问题的设计模式的想法吗?
【问题讨论】:
-
似乎
MyObject非常易变,不适合struct。 -
case语句似乎完全忽略了switch变量s。这真的有效吗? -
如果您有不同的转换并且必须手动编码,那么我没有得到“具有无限可能性的开关”声明,您仍然必须编写无限转换,那么重点在哪里?
-
ToSystemB、ToSystemX等有哪些代码?如果它们真的完全不同,那么你的问题本质上很复杂。我能想到的唯一方法是将逻辑编码到数据文件中(或者不编码,但实际上将其写入您将发明的 DSL 中)。这样,C# 代码只需要找到一个正确的文件,读取它并运行它。文件名可以以initial系统开头,以terminal系统结尾。 -
不完全清楚你最终想要达到的目标,但你可能想看看TypeConverter。如果您尝试自动计算是否存在通过 C1、C2、..CN 类型将 A 转换为 B 的路径,那么您应该阅读图上的路径查找。您还可以查看“计量单位”转换的实现...
标签: c# generics enums coordinate-transformation