工厂应该设置模型属性
本文关键字:模型 属性 设置 工厂 | 更新日期: 2023-09-27 17:50:37
作为整个soa编程工作的一部分,我创建了一个工厂接口&基本框架API中的抽象工厂。
人们已经开始使工厂的Create方法过载。问题是人们用模型属性重载了Create方法(从而期望工厂填充它们)。
我认为属性设置不应该由工厂来完成。我错了吗?
public interface IFactory
{
I Create<C, I>();
I Create<C, I>(long id); //<--- I feel doing this is incorrect
IFactoryTransformer Transformer { get; }
IFactoryDataAccessor DataAccessor { get; }
IFactoryValidator Validator { get; }
}
更新-对于那些不熟悉SOLID原则的人,这里有一些:
单一责任原则
它指出每个对象都应该有一个单独的职责,并且这个职责应该完全被类
打开/关闭原则
这个原则的含义是,当你收到一个需要添加到你的应用程序中的特性的请求时,你应该能够在不修改旧类的情况下处理它,只需要添加子类和新的实现。
依赖倒置原则
它说你应该解耦你的软件模块。要实现这一点,您需要隔离依赖项。
我有90%的把握知道答案。但是,我希望已经在使用SOLID的人能够进行一些好的讨论。谢谢你提出的宝贵意见。
UPDATE -那么我认为一个SOLID工厂应该做什么?
IMHO一个SOLID工厂提供适当的对象实例…但是这样做的方式隐藏了对象实例化的复杂性。例如,如果您有一个Employee模型…你可以让工厂给你弄一个合适的。DataAccessorFactory会给你正确的数据访问对象,ValidatorFactory会给你正确的验证对象等等。
例如:var employee = Factory.Create<ExxonMobilEmployee, IEmployee>();
var dataAccessorLdap = Factory.DataAccessor.Create<LDAP, IEmployee>();
var dataAccessorSqlServer = Factory.DataAccessor.Create<SqlServer, IEmployee>();
var validator = Factory.Validator.Create<ExxonMobilEmployee, IEmployee>();
更进一步,我们将…
var audit = new Framework.Audit(); // Or have the factory hand it to you
var result = new Framework.Result(); // Or have the factory hand it to you
// Save your AuditInfo
audit.username = 'prisonerzero';
// Get from LDAP (example only)
employee.Id = 10;
result = dataAccessorLdap.Get(employee, audit);
employee = result.Instance; // All operations use the same Result object
// Update model
employee.FirstName = 'Scooby'
employee.LastName = 'Doo'
// Validate
result = validator.Validate(employee);
// Save to SQL
if(result.HasErrors)
dataAccessorSqlServer.Add(employee, audit);
UPDATE -那么为什么我坚持这种分离?
我觉得责任分离可以实现更小的对象,更小的单元测试,并且增强了可靠性& &;维护。我承认这样做的代价是创造更多的对象……但这就是固体工厂保护我的…它隐藏了收集和实例化上述对象的复杂性。
我想说这是坚持DRY原则,只要它是简单的值布线我不认为这是问题/违反。而不是用
var model = this.factory.Create();
model.Id = 10;
model.Name = "X20";
分散在你的代码库中,把它们放在一个地方总是更好。未来的合同变更、重构或新需求将更容易处理。
值得注意的是,如果这样的对象创建和立即属性设置是常见的,那么这就是您的团队已经开发的模式,开发人员添加重载只是对这一事实的响应(值得注意的是,这是一个很好的响应)。应该引入一个API来简化这个过程。同样,如果它缩小到简单的赋值(就像你的例子),我会毫不犹豫地保留重载,特别是如果它是你经常注意到的东西。当事情变得更复杂时,这将是发现新模式的标志,也许这时您应该求助于其他标准解决方案(例如构建器模式)。
假设您的工厂接口是从应用程序代码中使用的(与基础结构组合根相反),它实际上代表了一个服务定位器,可以将其视为依赖注入方面的反模式。参见Service Locator: roles vs. mechanics。
注意下面的代码:
var employee = Factory.Create<ExxonMobilEmployee, IEmployee>();
只是语法糖。它不能消除对具体ExxonMobilEmployee
实现的依赖。
您可能还对弱类型与强类型消息通道和没有服务位置的消息调度(它们说明了这些接口如何违反SRP)以及Mark Seemann的其他出版物感兴趣。
经过6个月的依赖注入经验,我只发现工厂应该设置属性的情况很少:
-
如果设置器标记为
internal
,并且该属性仅由工厂设置一次。这通常发生在只有get
- ter属性的接口上,其实现预计将通过工厂创建。 -
当模型使用属性注入时。我很少看到使用属性注入的类(我也尽量避免构建这些类),但是当我确实看到一个类,并且所需的服务只在其他地方可用时,这是您别无选择的情况。
对于底线,将public set
排除在工厂之外。只设置标记为internal
的属性。如果允许,让客户端决定需要设置哪些属性。这将使您的工厂清除不必要的功能。