是否有更优雅的方式(或模式)来实现相关类的组

时间:2013-01-02 00:34:00

标签: oop class design-patterns generics

我正在尝试实现各种相关类组,有点像这样:

  • MySQLDatabase
  • MySQLTable(引用MySQLDatabase)
  • MySQLRecord(引用MySQLTable)
  • PostGreDatabase
  • PostGreTable(引用PostGreDatabase)
  • PostGreRecord(引用PostGreTable)
  • Oracle数据库
  • ...

由于相关类(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> {}

...

我需要这种架构能够:

  • 防止错误的引用。

Ex: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 :(得分:0)

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

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

可以假设MySQLTable也是使用泛型定义的,因为你将它定义为Table的子代:

MySQLTable<Something> : Table<MySQLDatabase>

您如何定义 Something ?这没有意义。

如果您使用Generics实现此目的:

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

我不认为这是使用泛型的必要和充分条件。

答案 1 :(得分: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) { }
    }