有没有一种更优雅的方式(或一种模式)来实现相关类的分组?

3

我试图实现一些相关类的分组,类似于这样:

  • MySQLDatabase
  • MySQLTable(引用MySQLDatabase)
  • MySQLRecord(引用MySQLTable)
  • PostGreDatabase
  • PostGreTable(引用PostGreDatabase)
  • PostGreRecord(引用PostGreTable)
  • OracleDatabase
  • ...

由于相关类(如MySQLTable、PostGreTable等)有很多共享代码,因此我使用抽象父类和泛型来实现,就像这样:

class Database {}

class Table<DatabaseType> where DatabaseType : Database 
{
  public DatabaseType FDatabase; //this is what I mean by "references"
}

class Record<TableType, DatabaseType> where 
  DatabaseType : Database
  TableType : Table<DatabaseType> 
{
  public TableType FTable;
}

class MySQLDatabase : Database {}

class MySQLTable : Table<MySQLDatabase> 
{
  public string FCharset;
}

MySQLRecord : Record<MySQLTable, MySQLDatabase> {}

...

我希望这个架构能够:

  • 防止错误的引用。

例如:MySQLTable不能引用PostGreDatabase或OracleDatabase,只能引用MySQLDatabase。

  • 使程序员能够访问对象特定属性而无需进行强制类型转换。

例如:

SomeMySQLRecord.FTable.FCharset = 'UTF-8'; 

代替
((MySQLTable)SomeMySQLRecord.FTable).Charset = 'UTF-8'; 

我正在寻求更加优雅的方法(或模式)来处理此事,因为真实的类组包含超过3个类,而泛型实在让代码变得混乱。例如:
MyType : Type1<GType1, GType2, GType3, GType4> where
  GType1 : Type2,
  GType2 : Type3<GType1>,
  GType3 : Type4<GType1, GType2>,
  GType4 : Type5<GType2, GType1, Type2, GType3>
2个回答

0

我会选择稍微不同的路线,虽然我不完全确定在你的情况下是否可行:

     public class Provider { }

    public class Oracle : Provider { }

    public class AbstractDatabase<T> where T : Provider
    {
        // Your base code here
    }

    public class AbstractTable<T> where T : Provider
    {
        public AbstractDatabase<T> FDatabase { get; set; }
        // Your base code here
    }

    public class AbstractRecord<T> where T : Provider
    {
        public AbstractTable<T> FTable { get; set; }
    }

    public class OracleDatabase : AbstractDatabase<Oracle> { }

    public class OracleTable : AbstractTable<Oracle>
    {
        public new OracleDatabase FDatabase { get; set; }

        // Your strongly typed code
        public OracleTable(OracleDatabase parent) { }
    }

但是泛型的潜在问题仍然存在。 - Daniel Santos
我明白了,你能给一个更具体的例子吗?我只是想看看这样做是否会减少它。 - Sebastian K
好的,我认为在这个解决方案中,您将不会看到这种链接问题,因为您最终会得到像这样的代码:OracleRecord:AbstractRecord <Oracle>等...而在您的情况下,您必须提供两个参数,然后是三个等等...使用这个解决方案,只需要始终提供一个参数-提供程序类型即可。 - Sebastian K
你能否将我的FDatabase和FTable字段添加到你的代码中,这样我就可以更好地理解你的解决方案吗? - Daniel Santos
不行。我试图避免将OracleTable.FDatabase强制转换为OracleDatabase的需要。 - Daniel Santos
显示剩余3条评论

0

对我来说,这里的泛型并没有意义。看看你自己的代码:

Table<DatabaseType : Database>
MySQLTable : Table<MySQLDatabase>

人们会认为MySQLTable也应该使用泛型进行定义,因为你是将它定义为Table的子类。
MySQLTable<Something> : Table<MySQLDatabase>

你如何定义这里的“Something”?这没有意义。
如果你要使用泛型来实现这个:
例如:MySQLTable不能引用PostGreDatabase或OracleDatabase,只能是MySQLDatabase。
我不认为这是使用泛型的必要和充分条件。

是的,我正在使用泛型来实现这一点,因为我能想到的另外两种选择是:复制粘贴我的大量代码并仅更改类型,或者使用抽象类型声明属性,例如在MySQLRecord上拥有一个Table属性而不是MySQLTable属性,并进行大量样板文件类型验证以确保此属性只能接受MySQLTable。这两种方法都违反了DRY原则。 - Daniel Santos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接