包含子属性的子类的设计模式
本文关键字:子类 设计模式 属性 包含 | 更新日期: 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创建另一个抽象。