使用属性作为工厂方法

D.R*_*.R. 4 c# properties factory-method

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

使用抽象属性作为工厂方法是不好的风格?例如

protected abstract TRequired NewTRequired { get; }
Run Code Online (Sandbox Code Playgroud)

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

Jon*_*Jon 8

肯定应该使用一种方法,因为访问这个成员有所作为.调用方法是让代码在这方面说话的好方法.

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

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

var prototype = Factory.NewTRequired;
Run Code Online (Sandbox Code Playgroud)

我特意把结果到一个名为变量prototype,以便更好地表明,该代码甚至是知情的读者可以很容易地揭去:它不会是不合理的看到这一点,认为"正确的,所以NewTRequired是原型对象X" .那个读者肯定会对这样的代码结果感到惊讶:

var eq = object.ReferenceEquals(prototype, Factory.NewTRequired);
Run Code Online (Sandbox Code Playgroud)

将其与工厂方法进行对比.现在这段代码可能会散发出轻微的气味:

// 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();
Run Code Online (Sandbox Code Playgroud)

这段代码永远不会让你大吃一惊:

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

治所在今真是一个著名的例子应该一直跟着,但没有DateTime.Now属性.


Ree*_*sey 5

我会推荐一种方法:

protected abstract TRequired CreateRequired();
Run Code Online (Sandbox Code Playgroud)

创造意味着"工作"的发生.这更适合方法与属性,因为属性获取器意味着通常会在不执行大量代码的情况下快速返回.

甚至你的问题标题"属性作为工厂方法"意味着工厂方法应该是一种方法.