2012-03-25 105 views
2

我有以下的策略模式实现:使用工厂创建一个策略

public abstract class RetrievalStrategy { 
    public abstract List<MyObject> retrieve(); 
} 

public class LimitRetrievalStrategy extends RetrievalStrategy { 
    public int limit; 
    public LimitRetrievalStrategy(int limit) { 
     this.limit = limit; 
    } 
    public List<MyObject> retrieve() { 
     // fill up the list and return it, limiting to 'limit' results 
     return new ArrayList<MyObject>(limit); 
    } 
} 

public class SpeedRetrievalStrategy extends RetrievalStrategy { 
    public int speed; 
    public SpeedRetrievalStrategy(int speed) { 
     this.speed = speed; 
    } 
    public List<MyObject> retrieve() { 
     // do something with the speed and return list again 
     return new ArrayList<MyObject>(); 
    } 
} 

我的客户端应用程序接收无论是速度还是从用户的限制(可能还有其它参数)。我想创建一个工厂类,它将返回基于具有值的参数和不具有参数的适当策略。我不希望客户决定应该返回哪个策略。如果工厂createStrategy(params)方法对每个参数都有if语句,并且取决于不同的组合(假设还有其他策略类),那么返回具体策略类? 这样做的正确方法是什么?

+1

这就是我会做的。你有什么疑问? – 2012-03-25 16:31:04

+0

很难延伸。 – 2012-03-25 16:34:30

+0

TBH,这听起来像是一个非OO维护的噩梦,让工厂使用“is-parameter-set”启发式来猜测使用哪种策略。如果你最终得到两个使用完全相同参数的策略呢?您将无法使用此工厂设计。 – 2012-03-25 16:38:18

回答

1

不,方法签名中的返回值应该是通用接口或基类。

工厂必须通过if测试来确定要返回的具体类型,但这是不可避免的,除非您可以制作一个基于封装参数组合的组合键类的具体实例的Map。

4

哦,RetrievalStrategyFactory,从哪里开始?这听起来像是一个YAGNI overengineering。一种方法是创建一个枚举来指定“set”字段,假设每个参数有一个检索策略,并将其用作工厂。

public enum FieldParameter { 
    LIMIT { 
     RetrievalStrategy getRetrivalStrategy(int value) { 
      return new LimitRetrievalStrategy(value); 
     } 
    }, 
    SPEED { 
     RetrievalStrategy getRetrivalStrategy(int value) { 
      return new SpeedRetrievalStrategy(value); 
     } 
    }; 

    abstract RetrievalStrategy getRetrivalStrategy(int value); 
} 

然后客户端代码没有明确指定检索策略,但是当客户端代码告知您的代码字段中的用户提供其隐含给出。

+0

可能有多个值,一个策略可能需要很多参数。 – 2012-03-25 16:33:52

1

如果你需要扩展工厂的能力,你想要一个抽象工厂。这是工厂的一个工厂。一个抽象工厂可以有很多插件工厂,它们可以根据策略来确定使用哪个工厂。

这通常是不必要的复杂,你可以稍后添加,所以它不是你需要做的事情,以防万一你可能需要它。

相关问题