使用特性作为工厂方法

本文关键字:工厂 方法 | 更新日期: 2023-09-27 18:22:22

我有一个基类Base,它需要创建另一种类型TRequired的实例,但是,只有来自Base的派生类知道如何构造这些实例。

使用抽象属性作为工厂方法是一种糟糕的风格吗?例如

protected abstract TRequired NewTRequired { get; }

出于某种原因,我应该使用一种方法吗?有没有指导我为什么应该/不应该使用这里的房产?

使用特性作为工厂方法

您应该肯定使用方法,因为访问此成员。调用一个方法是让代码在这方面不言自明的好方法。

或者,如果您更喜欢另一种视角:成员的两次后续访问将返回不同的结果。一个好的经验法则是,在任何情况下都要使用一种方法,以免违反最小惊讶的原则。

这看起来像是在读取变量的结果,即使你知道NewTRequired是一个属性(而不是字段),你也知道它实际上运行的是任意代码:

var prototype = Factory.NewTRequired;

我有意将结果放入一个名为prototype的变量中,以更好地表明,即使是知情的读者也可以很容易地摆脱这段代码:看到这一点并认为"没错,所以NewTRequired是X的原型对象"并非没有道理。读者肯定会对这样的代码的结果感到惊讶:

var eq = object.ReferenceEquals(prototype, Factory.NewTRequired);

将此与工厂方法进行对比。现在这个代码可能会发出轻微的气味:

// hmmm... are we actually using this as a prototype?
// because it sure looks like an instance created just for the occasion.
var prototype = Factory.NewTRequired();

这个代码永远不会让你惊讶:

// obviously should be false, the code screams "I am creating new instances!"
var eq = object.ReferenceEquals(Factory.NewTRequired(), Factory.NewTRequired());

DateTime.Now属性是一个著名的例子,说明了这个规则确实应该遵循但没有遵循。

我建议使用一种方法:

protected abstract TRequired CreateRequired();

创造意味着"工作"的发生。与属性相比,这更适合方法,因为属性getter意味着通常会在不执行太多代码的情况下快速返回一些内容。

甚至你的问题标题"property as factory method"也暗示工厂方法应该是方法

属性是为"看起来像"字段的东西设计的,比如对象的位置。

每次获得一个新实例都会返回的属性是非常糟糕的设计。

你应该使用一个方法。