考虑以下针对正在Add
实例上执行的日志记录操作Update
/ Entity
的体系结构。
LogFactory
是Abstract Factory
,使用Add
通过构造函数接收Update
和DI
的两个工厂。
具体工厂AddLogFactory
和UpdateLogFactory
都实施ILogFactory
以生成ILog
。他们都需要Entity
来收集可记录的数据。
好吧,我希望一切都清楚,你承认Abstract Factory
模式到目前为止是正确的解决方案。
问题:
UpdateLogFactory
是一个例外,因为它需要额外的数据:ModifiedProperties
来创建一个前/后字符串(同时它的兄弟姐妹,即实现ILogFactory
的其他类型不需要这种类型数据; Entity
就足够了)。为了不打破ILogFactory
,我决定通过其构造函数将ModifiedProperties
提供给UpdateLogFactory
。
它解决了我的问题,但我觉得我在某种程度上作弊;我假装UpdateLogFactory
与其他人相似,而事实并非如此。
如果有人想用另一种具体类型替换UpdateLogFactory
,他怎么知道它需要ModifiedProperties
?
答案 0 :(得分:2)
实际上ModifiedProperties
是一个实现细节。任何ILogFactory
是否需要在格式之前和之后生成?我不这么认为。
无论如何,我认为ModifiedProperties
不应该被注入,但它们应该是ICanTrackPropertyChanges
等界面的一部分:
public interface ICanTrackPropertyChanges
{
IEnumerable<string> ModifiedPropertyNames { get; }
}
ICanTrackPropertyChanges
应由您的实体实施。因此,UpdateLogFactory
可以做出以下断言:
ICanTrackPropertyChanges trackable = entity as ICanTrackPropertyChanges;
// Design by contract wins!
Contract.Assert(trackable != null);
// And now access trackable.ModifiedProperties and produce the
// customized message for entity updates
这样,您就不需要提供ModifiedProperties
作为ILogFactory
的实现细节,但您相信实体可以在实现接口时跟踪属性更改。
您可以使用通用约束强制执行此操作:
public interface IUpdateLogFactory<TEntity> : ILogFactory
where TEntity : class, ICanTrackPropertyChanges
{
}
...并使用此接口实现可记录的实体更新。
此外,您还获得了改进:IUpdateLogFactory<TEntity>
实施不需要检查实体是否有ModifiedProperty
,因为已保证处理的实体已修改了整个IEnumerable<string>
属性在编译时!
答案 1 :(得分:0)
您是否混淆了抽象工厂和工厂方法?
您的图表不是GoF定义的抽象工厂:
你错过了:
如果您要将模式应用于您的问题,您将能够在createUpdateLog
方法上获得额外的参数(如下所示),但是您会遇到几个不上课的问题。 t fit(以粉色表示):
我怀疑你正在尝试使用Factory Method模式,它只有一个签名,这就是为什么你在UpdateLog
s的情况下遇到“例外”参数的问题。
如您所见,每个混凝土工厂只处理一种具体产品。
现在我将你的设计从问题插到这个模式: