Factory & Strategy patterns

2019-06-22 16:08发布

问题:

I need to create a class which will be responsible for result set processing but it might happen that different algorithms should be used to process that result set.

I am aware of the following options:

1) Use Strategy patern, below is pseudo code:

interface Strategy {
  processResultSet(ResultSet rs);
}

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

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

Context class will contain reference to Strategy and Client should pass the implementation of Strategy creating Context object, i.e.

class Context {
  private Strategy strategy;

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

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

The problem is that I don't want to pass strategy object to Context but I would like to create something like StrategyFactory which will be responsible for creation of concrete Strategy implementation. It would separate Client from Strategy - is it a good design?

Is it a mix of Strategy and Factory or in fact only Factory pattern?

回答1:

It's definitely a combination of Strategy and Factory - but I don't think that's bad. The patterns are intended to be combined and used with each other.

It is hard to tell with out seeing this design plan in context whether this is a good design or a bad one. With just the information you've given here it could go either way.

Seems like your head is in the right place, but let me just give you a word of warning: don't stretch too hard to separate your client from your strategy. I have done this in the past and it lead to a convoluted mess which would have been far simpler had I just allowed a little connection between the two portions of my code. Separation is good, but struggling to maintain perfect separation can lead to bad code and all kinds of problems.



回答2:

We have used this is many different parsing scenarios and it certainly works. I have blogged about this with a code example: http://www.herrodius.com/blog/136

The trick we use is to give the strategy interface an extra "canProcess" method which simply returns a boolean if the strategy is able to deal with the data. The factory then simply loops through all its strategies and asks each one if it can work with the data. If one can, we return that strategy or execute the strategy.



回答3:

In the scenario you depict, there wouldn't really be a need for a Context, which would instead be replaced by the Factory you desire. The strategy pattern in this case is just overhead and an unneeded layer of complexity. All you need is an interface or abstract class, implementations, and a Factory or Proxy to retrieve the implementations.



回答4:

Anny comments related to my thoughts:

1) There is a Service - Singleton. 2) It contains a reference to DAO class - it is also a singleton. 3) In DAO there is a method which retrieves ResultSet: ResultSet rs = ps.executeQuery(); I would like to create an appropriate strategy inside DAO to process this result set. I can't pass this strategy in DAO constructor because it is specific for the incomming request. Passing it in the constructor would make it the same for all incomming request. So I decided to create a Factory inside DAO (DAO object instance) and inside a method I'm going to create an appropriate strategy (based on the request - local object) from the factory and use it to process the resultset.

Is this solution good in your opinion?



回答5:

I think strategy pattern should go with a factory pattern. And in a way you used it is absolutely correct. Secondly, it would be better if you kept context class as an abstract class so that you can extend different contexts as per your requirement. Rest of the things seems good but according to the example you mentioned I think it wasn't necessary but you have used it in right way.