C# 如何存储派生类中用于初始化其基类的工厂?
假设您有某种工厂创建的资源,在构建后仍然属于工厂,如下所示:C# 如何存储派生类中用于初始化其基类的工厂?,c#,.net,constructor,initialization,factory,C#,.net,Constructor,Initialization,Factory,假设您有某种工厂创建的资源,在构建后仍然属于工厂,如下所示: public class Resource : IDisposable { public void Dispose() { /* ... */ } } public class ResourceManager : IDisposable { public Resource Load() { /* create resource and add to list */ } public void Dispose() { /*
public class Resource : IDisposable {
public void Dispose() { /* ... */ }
}
public class ResourceManager : IDisposable {
public Resource Load() { /* create resource and add to list */ }
public void Dispose() { /* dispose all loaded resources in list */ }
}
现在您有了一个基类,它需要构造函数中的资源实例来初始化:
public class Fooificator {
public Fooificator(Resource resource) {
this.resource = resource;
}
private Resource resource;
}
从此类基类派生的类如何构造资源
,而不丢失对工厂的引用
使用静态方法的天真方法无法记住工厂(除了丑陋的黑客行为,比如将其存储在静态字段中,以便构造函数在基类构造完成后提取,或者使用两阶段初始化,其中资源通过名为Initialize()
方法的构造函数提供给基类)
一种可能的解决方法是命名构造函数习惯用法:
public class DefaultFooificator : Fooificator, IDisposable {
public static DefaultFooificator Create() {
ResourceManager resourceManager = new ResourceManager();
DefaultFooificator fooificator = new DefaultFooificator(
resourceManager.Load()
);
fooificator.resourceManager = resourceManager;
return fooificator;
}
private DefaultFooificator(Resource resource) : base(resource) {}
private ResourceManager resourceManager;
}
但是,在解决存储ResourceManager
引用的问题时,这将不允许从DefaultFooificator
派生更多的类
有什么优雅的解决方案可以让我进一步从DefaultFooificator
派生,或者以其他方式存储ResourceManager
引用吗?为什么从Fooificator
派生的类要负责构造资源?为什么不能将此依赖项注入到它的构造器是什么
public class DefaultFooificator : Fooificator
{
public DefaultFooificator(Resource resource) : base(resource) {}
}
您可以将资源的创建推迟到<代码> FooPixor工厂> /Cuff>。
< P>我认为您应该考虑您的类是否过于紧密耦合。如果资源具有公共构造函数,每个人都可以创建一个实例并将其作为引用给FooPixor构造函数。这实际上是一件好事。
看起来不那么吸引人的是,您似乎有一个要求,即只有ResourceManager.Load创建的资源才能合法使用(顺便说一句,这违反了命令/查询分离)。但是,API没有强制执行此约束
您应该通过将资源构造函数设置为内部,或者通过解除ResourceManager约束来强制执行此约束
内部构造函数倾向于拉紧类耦合的方向,所以我认真考虑第二个选项。
或者,更改Fooificator的构造函数以引用ResourceManager,或者可能是Func
如果没有更多的上下文,我想很难给出一个更好的答案。同意,但如果不让人们解释几页,就很难陈述问题。在实际的代码库中,这是一个XNA游戏,Resource
和ResourceManager
(他们的真名是Effect
和ContentManager
)是由微软的框架提供的,不幸的是,这不在我的控制范围之内类已经使用了一个internal
构造函数,我只是为了精简代码而省略了它。向Fooificator
添加ResourceManager
引用会破坏封装,因为Resource
实例在实际代码中可以通过ResourceManager
或通过静态方法创建dResource.CompileFromFile()
(也不在我的控制范围内),因此,至少在一种情况下,ResourceManager
将是null
@Cygon:感谢您的解释。每当我发现现有API不充分,但我无法更改它时,我通常会创建一个屏蔽我的接口-一个反腐败层,如果您愿意的话。这可能是一个创建Resource inst的接口例如我提到的Func,函数/委托基本上只是匿名的单方法接口…这就是我的最后一个示例所做的。可能你指的是一个抽象工厂,而我的命名构造函数实际上是一个工厂方法,但结果是一样的。这两种情况都不允许派生更多的类从DefaultFooificator
中,我的原因是运行时不能基于静态方法派生,而您的方法是因为它会将派生类拉入提供DefaultFooificator
的资源的职责中,其中构造它所需的数据是Defa的私有实现细节咨询者
。
public class DefaultFooificator : Fooificator
{
public DefaultFooificator(Resource resource) : base(resource) {}
}