所以我读到的几乎每一篇关于纯粹主义者关于oop的文章,他们总是强调使用静态方法是如何反模式的,并且破坏了代码的可测试性。另一方面,每次我使用工厂(不管编程语言如何)寻找一些示例代码,特别是为了对象构造的目的,我都会在工厂类中看到一个静态方法,返回构造的对象。(以下伪码)
class ProductFactory() {
public static function make(string name): Product
{
if(name contains TV)
return new TVProduct(name)
else
return new HomeAppliance(name);
}
}
product = ProductFactory->make('LCD TV');对我来说,这看起来很好,因为最终我想要一个对象的实例,而不是工厂的实例,如下所示。
productFactory = new ProductFactory();
product = productFactory->make('LCD TV');我的问题是两方面的。
使用工厂的真正方式是什么?工厂中的静态方法是正确和被接受的使用方法吗?
2-如何为使用静态方法的工厂编写单元测试?
我希望我对使用工厂来构建对象的理解在基本层面上没有缺陷。
发布于 2020-02-15 06:18:15
实际上有两种不同的模式,它们的名称中有“工厂”,它们有不同的用途:
关于单元测试,静态工厂方法与直接构造函数调用完全相同:它们不能被模拟出来(不诉诸巫毒魔法),但是通常使用它们的类型是您根本不关心的类型,比如值对象。对于任何比这更复杂的东西(特别是那些涉及外部依赖项的),您希望创建一个工厂接口并将其注入客户机(并在单元测试中模拟工厂)。
发布于 2020-02-13 11:29:38
在其他“好”代码中有大量静态方法的例子,但是是的,通常使用静态方法被认为是不好的做法。当您在这里讨论时,主要的论点之一是它使测试变得困难。
所以要按反序回答你的问题..。
你可以测试工厂本身没有问题,但是你能测试一些使用工厂的东西吗?或者使用工厂内部返回的对象,您想要在其中模拟该对象?
我不会说它不可能,但它不可能没有技巧。
不是的。静力学可能引起的潜在问题的最简单的解决方法就是不使用静力学。然后,您的代码将从
product = ProductFactory->make('LCD TV');至
product = this.injectedIProductFactory->make('LCD TV');在计划中付出的代价不算太大。
发布于 2020-02-14 21:56:44
或者,对于另一个问题中所建议的方法,可能会有一些硬编码但仍然“抽象”的代码:
class ProductFactory() {
// here factories are injected; could be real
public ProductFactory(ITVProductFactoru tvProductFactory, IHomeApplianceFactory homeApplianceFactory)
{
this->tvProductFactory = tvProductFactory;
this->homeApplianceFactory = homeApplianceFactory;
}
public make(string name): Product
{
if(name contains TV)
return this->tvProductFactory->make(name)
else
return this->homeApplianceFactory->make(name);
}
}因此,在组合根中,不需要有选择逻辑,而是将其移到抽象代码中,例如可以进行测试。
https://softwareengineering.stackexchange.com/questions/405107
复制相似问题