使用特性作为工厂方法
本文关键字:工厂 方法 | 更新日期: 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"也暗示工厂方法应该是方法。
属性是为"看起来像"字段的东西设计的,比如对象的位置。
每次获得一个新实例都会返回的属性是非常糟糕的设计。
你应该使用一个方法。