包含子属性的子类的设计模式

本文关键字:子类 设计模式 属性 包含 | 更新日期: 2023-09-27 17:59:17

我想知道是否有一种设计模式可以解决这个问题。我有一个看起来像这样的结构:

    public abstract class DBAccess
    {
         protected MetaData MetaData;
    }
    public class OldDBAccess: DBAccess
    {
         //this class will set metatData = new OldDBMetaData(); in the constructor
    }
    public class NewDBAccess: DBAccess
    {
         //this class will set metaData = new NewMetaData(); in the constructor
    }
    public abstract class MetaData
    {
        //some variables and methods that belong to all MetaData objects
    }
    public class OldMetaData : MetaData
    {
        string oldName;
        //some variables and methods that belong to only OldDBMetaData objects
    }
    public class NewMetaData : MetaData
    {
        //some variables and methods that belong to only NewDBMetaData
    }

我希望能够在OldDBAcess中调用一个方法,该方法设置属于OldDBMetaData的属性。由于元数据是一个元数据对象,而不是OldDBMetaData对象,所以到目前为止我不得不这样做:

    //method in OldDBAccess
    public void SetOldName(string name)
    {
       if(metaData is OldMetaData)
       {
           OldMetaData metaData = (OldMetaData)MetaData;
            if (metaData == null)
                // metaData isn't of type OldMetaData
            else
                metaData.oldName = name;
        }
     }

这很好,我只是不想每次调用方法时都要检查元数据的类型是否为OldMetaData。我知道它是这种类型的,因为我在构造函数中将它设置为这种类型。我想在派生类或基类中使用metaData属性,所以我不能只在每个DBAccess类中创建属性。这种结构有没有设计模式或简单的方法?

包含子属性的子类的设计模式

这可以满足您的需要:

public sealed class OldDbAccess : DbAccess
{
    protected override MetaData CreateMetaData()
    {
        // return old metadata
    }
}
public class DbAccess
{
    public DbAccess()
    {
        this.MetaData = CreateMetaData();
    }
    protected virtual MetaData CreateMetaData()
    {
        // return new metadata
    }
}

如果你使用ReSharper(或类似的),它可能会对你在构造函数中调用虚拟成员的问题大发雷霆,但只要你的CreateMetaData()调用不依赖于派生类的构造函数中设置的任何内容,那就没问题。

正如我从您的案例中了解到的,它是这样的:

public abstract class MetaData
{
    public string Name { get; set; }
}
public class OldDBMetaData : MetaData
{
    public string OldName { get; set; }
}
public class NewDBMetaData : MetaData
{
    public string NewName { get; set; }
}

例如,您的问题将发生在TestSetName方法中

public abstract class DBAccess
{
    protected MetaData metaData;
}
public class OldDBAccess : DBAccess
{
    public OldDBAccess()
    {
        metaData = new OldDBMetaData();
    }
    public void TestSetName(string name)
    {
        // You want to do this one, but you cannot because the abstract class MetaData doest not exist OldName property
        // metaData.OldName = name;
        // I can simple resolve this problem by cast this to the OldDBMetaData
           ((OldDBMetaData)metaData.OldName) = name; 
    }
}

在我看来,我们可以通过CAST解决这个问题,但它将在实施过程中结合起来。如果您想避免这种情况,可以为OldDBMetaData和NewDBMetaData创建另一个抽象。