工厂模式和策略模式

5
我需要创建一个类,负责结果集处理,但可能需要使用不同的算法来处理该结果集。
我知道以下选项:
1)使用策略模式,下面是伪代码:
interface Strategy {
  processResultSet(ResultSet rs);
}

class StrategyA implements Strategy {
  processResultSet(ResultSet rs);
}

class StrategyB implements Strategy {
  processResultSet(ResultSet rs);
}

Context类将包含对Strategy的引用,客户端应该传递实现Strategy创建Context对象,即

class Context {
  private Strategy strategy;

  public Context(Strategy strategy) {
    this.strategy = strategy;
  }

  public doSomething(rs) {
    strategy.processResultSet(rs);
}

问题在于我不想将策略对象传递给上下文,而是想创建类似于StrategyFactory的东西,它将负责创建具体的策略实现。这将把客户端与策略分离 - 这是一个好的设计吗?
这是策略模式和工厂模式的混合还是仅仅是工厂模式?

如果你将客户端与其策略实现分离,那么当工厂(或者可能是抽象工厂)尝试实例化对象时,它将如何知道要实现哪个策略呢? - Justin Niessner
工厂可能不是从客户端获取该信息,而是从其他地方(例如配置文件)获取。如果不知道他的具体实现,就无法确定。 - Daniel Bingham
两种观点都是有道理的,@Alcon。但如果我们拥有所有细节,做出明智的建议会更容易些。 - Justin Niessner
  1. 有一个Service - Singleton。
  2. 它包含对DAO类的引用 - 同样也是单例模式。
  3. 在DAO中存在一种检索ResultSet的方法: ResultSet rs = ps.executeQuery();
我想在DAO内部创建一个适当的策略来处理这个结果集。我不能将此策略传递到DAO构造函数中,因为它是特定于请求的。将其传递到构造函数中将使其对所有传入的请求都相同。
- Kumar
所以我决定在DAO内部创建一个工厂,并在方法内部创建一个适当的策略(基于请求)来处理结果集。 - Kumar
5个回答

9

这绝对是策略模式和工厂模式的结合 - 但我认为这并不是坏事。这些模式旨在相互组合使用。

如果没有看到上下文中的设计计划,很难确定这是一个好的设计还是一个坏的设计。只有你提供的信息,它可能会走向任何方向。

看起来你的想法是正确的,但我想提醒你:不要过于强调将客户端与策略分开。我过去曾经这样做,结果导致了一个混乱的代码,如果我允许两个部分之间有一点联系,那么问题会变得简单得多。分离是好的,但是过于强调完美分离可能会导致糟糕的代码和各种问题。


更加精确地说。 我有:1)Service类 2)Service类包含对JDBCDAO类的引用。 3)JDBCDAO类包含一个方法,其中执行以下操作:ResultSet rs = ps.executeQuery();我不想将rs返回给service,而是让JDBCDAO对象处理它并返回适当的对象,因此我希望创建此Factory(创建适当的Strategy)作为JDBCDAO类的成员。 - Kumar

2
我们在许多不同的解析场景中使用了这种方法,它确实有效。我已经发表了一篇带有代码示例的博客文章:http://www.herrodius.com/blog/136 我们使用的技巧是给策略接口添加一个额外的“canProcess”方法,该方法仅返回一个布尔值,指示策略是否能够处理数据。然后,工厂简单地循环遍历其所有策略,并询问每个策略是否可以处理数据。如果其中一个可以,我们就返回该策略或执行该策略。

0
在您描述的情况下,实际上不需要Context,而应该用您想要的Factory来替代。在这种情况下,策略模式只是额外的开销和不必要的复杂性层。您只需要一个接口或抽象类、实现以及一个工厂或代理来检索实现即可。

2
如果他使用接口和实现来表示不同的处理算法,那么根据定义,这就是策略模式,不是吗? - Daniel Bingham

0

关于我的想法,您有什么评论:

1)有一个服务 - Singleton。2)它包含对DAO类的引用 - 它也是单例。3)在DAO中有一个检索ResultSet的方法:ResultSet rs = ps.executeQuery(); 我想在DAO内创建一个适当的策略来处理这个结果集。我不能在DAO构造函数中传递此策略,因为它是特定于传入请求的。将其传递到构造函数中会使所有传入请求都相同。所以我决定在DAO内部创建一个工厂(DAO对象实例),并在方法内部根据请求(本地对象)从工厂创建一个适当的策略,并使用它来处理结果集。

您认为这个解决方案好吗?


不,这是过度设计了。只需在DAO类中实现逻辑,而无需使用工厂或策略。如果在实现过程中或之后发现任何常见的或样板式的代码,请务必重构您的代码。但是首先不要犹豫,用简单的“if”让它正常工作。 - eljenso
单例模式以让代码难以测试而恶名昭彰。你考虑过可测试性吗? - TrueWill

0

我认为策略模式应该与工厂模式一起使用。你现在的使用方式是完全正确的。其次,最好将上下文类保留为抽象类,这样可以根据需要扩展不同的上下文。其他方面看起来都很好,但根据你提到的例子,我认为这并不是必要的,但你使用它的方式是正确的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接