目前我有:
class EntityFOO
{
EntityFOO LoadFromXml(XDocument) {...}
EntityFOO LoadFromDB(string) {...}
}
class EntityBAR
{
EntityBAR LoadFromXml(XDocument) {...}
EntityBAR LoadFromDB(string) {...}
}
我想重构并提取一个界面。我想要这样的东西:
abstract class Entity
{
static string DatabaseConnectionString = "shared_across_implementations";
abstract Entity LoadFromXml(XDocument);
abstract Entity LoadFromDB(string);
}
class EntityBAR : Entity
{
EntityBAR LoadFromXml(XDocument) {...}
EntityBAR LoadFromDB(string) {...}
}
请注意Entity
的实现,返回自己的类型EntityBAR
而不是父Entity
。并假设我不得不以某种方式使用<Generics>
。
答案 0 :(得分:2)
这样的东西?:
abstract class Entity<T> where T : Entity<T>
{
static string DatabaseConnectionString = "shared_across_implementations";
abstract T LoadFromXml(XDocument);
abstract T LoadFromDB(string);
}
class EntityBAR : Entity<EntityBAR>
{
EntityBAR LoadFromXml(XDocument) {...}
EntityBAR LoadFromDB(string) {...}
}
当然没有经过测试,并且Entity<T> where T : Entity<T>
通过使我成为某种奇怪的类型递归问题而弄乱了我的直觉。但我并不认为这是一个问题。
虽然我更关心的是那些LoadFrom...
方法。如果那些类型本身的工厂,它们不是static
?哪个会改变任何类型的继承方案。 我觉得有人需要一个实例来构建一个实例。
使用string
和XDocument
参数的构造函数可能更有意义吗?而且由于构造者没有返回类型,这会使问题没有实际意义。像这样结构的东西(也是徒手和未经测试的伪代码):
abstract class Entity
{
static string DatabaseConnectionString = "shared_across_implementations";
protected Entity(XDocument) {...}
protected Entity(string) {...}
}
class EntityBAR : Entity
{
public EntityBAR(XDocument) : base(XDocument) {...}
public EntityBAR(string) : base(string) {...}
}
当然,除非构建/初始化对象的操作非常重并且本身涉及其他依赖项。在这种情况下,构造函数并不总是一个安全的地方,设计会调用单独的Factory对象。 那些可以基于实例并返回这些实例。
但是在对象本身上进行基于实例的初始化步骤 本质上意味着消费代码需要手动记住构建任何给定对象是一个两步过程。这引发了潜在的错误和其他逻辑问题。