我有许多实现相同接口的算法类;另一个“工厂”类负责通过配置参数实例化正确的算法类,然后在该实例上调用 start 方法。
我想将算法类的构造函数(或任何其他实例创建机制)的可见性仅限于工厂类。
我该如何解决这个问题?我能想到的唯一干净的解决方案是将这些类移动到不同的 .dll 中并将算法类更改为私有,但这不是我现在想要做的。
我有许多实现相同接口的算法类;另一个“工厂”类负责通过配置参数实例化正确的算法类,然后在该实例上调用 start 方法。
我想将算法类的构造函数(或任何其他实例创建机制)的可见性仅限于工厂类。
我该如何解决这个问题?我能想到的唯一干净的解决方案是将这些类移动到不同的 .dll 中并将算法类更改为私有,但这不是我现在想要做的。
这不是你想听到的答案,但是:不要。
通过构造该构造函数private/internal/protected
,您很难测试算法,并且还阻止了 API 的任何消费者手动选择他们自己的实现而不是使用工厂。
我想说让构造函数公开,只要确保在构造函数中声明了所需的每个依赖项。这是我对构造函数的各种修饰符的看法:
public
- 每个人都可以访问你的构造函数,并且你可以测试这个类 -这很好。protected
- 子类可以访问构造函数。这没关系,但仅真正用于抽象类和/或构造函数链接。internal
- 您将构造函数的使用限制为InternalsVisibleTo
(朋友)程序集。这意味着您的程序集中的任何人都可以正常构造它,但其他程序集必须明确地使用InternalsVisibleTo
或被迫使用您的工厂,从而将算法与工厂耦合。private
- 用于隐藏默认构造函数(尽管如果创建具有至少一个参数的构造函数,则不需要这样做),或仅创建可链接的构造函数。TL; DR - 我建议不要制作constructor internal
。通过这样做,您还不如创建类 internal
(您通过它们的接口而不是它们的类来引用算法,对吗?)
另一种解决方案是实现类private
并将它们嵌套在工厂中。让他们都实现一个通用接口(他们应该已经这样做了)并将接口暴露给应用程序的其余部分。这仍然不能避免难以测试的问题。
也许你会对下面的示例感到满意(是的,我知道不应该正常使用反射......)
public class Algorithm
{
private Algorithm()
{
}
public void SomeMethod()
{
}
}
public static class Factory
{
public static Algorithm Create()
{
var constructor = typeof(Algorithm).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[0], null);
return (Algorithm)constructor.Invoke(null);
}
}
在这里,您可以通过 Factory.Create 创建算法实例,而不是通过新算法。