抽象工厂:当具体工厂需要额外数据时

时间:2015-06-20 12:14:12

标签: design-patterns abstract-factory factory-method

考虑以下针对正在Add实例上执行的日志记录操作Update / Entity的体系结构。

LogFactoryAbstract Factory,使用Add通过构造函数接收UpdateDI的两个工厂。 具体工厂AddLogFactoryUpdateLogFactory都实施ILogFactory以生成ILog。他们都需要Entity来收集可记录的数据。 好吧,我希望一切都清楚,你承认Abstract Factory模式到目前为止是正确的解决方案。

enter image description here

问题:

UpdateLogFactory是一个例外,因为它需要额外的数据:ModifiedProperties来创建一个前/后字符串(同时它的兄弟姐妹,即实现ILogFactory的其他类型不需要这种类型数据; Entity就足够了)。为了不打破ILogFactory,我决定通过其构造函数将ModifiedProperties提供给UpdateLogFactory。 它解决了我的问题,但我觉得我在某种程度上作弊;我假装UpdateLogFactory与其他人相似,而事实并非如此。

如果有人想用另一种具体类型替换UpdateLogFactory,他怎么知道它需要ModifiedProperties

2 个答案:

答案 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定义的抽象工厂:

Abstract Factory GoF

你错过了:

  • 两个或更多抽象产品类型(A,B)
  • 两个或更多createProduct方法(A,B)。

如果您要将模式应用于您的问题,您将能够在createUpdateLog方法上获得额外的参数(如下所示),但是您会遇到几个不上课的问题。 t fit(以粉色表示):

PlantUML diagram of Abstract Factory in this context

我怀疑你正在尝试使用Factory Method模式,它只有一个签名,这就是为什么你在UpdateLog s的情况下遇到“例外”参数的问题。

修改

这是Factory Method pattern

Factory Method Pattern from GoF

如您所见,每个混凝土工厂只处理一种具体产品。

现在我将你的设计从问题插到这个模式:

Factory Method applied