我问自己这个问题,我还没有想到这个。
我在想什么
当您拥有策略模式时,许多实现也使用工厂模式来检索特定策略。互联网上的大多数工厂示例都使用switch或if语句。当您不经常更改或添加策略时,这非常有效。但是,如果工厂用于动态查找策略并且策略经常更改和添加,该怎么办?那么这是程序员的全职工作。现在我有一种情况,我只想添加一个新的策略而不必更改工厂。换句话说,如何实现工厂模式,以便动态搜索策略。我如何列出所有可用的策略。
问题
当我在互联网上寻找这个时,我找不到一个合适的解决方案。我正在考虑使用反射库来执行此操作,但不建议在我看到的任何地方使用反射。那么如何实现动态工厂呢。或者是否有其他模式用于此目的?
示例
工厂:
public enum StrategyName { ImplementedStrategy1, ImplementedStrategy2, ImplementedStrategy3 };
public class StrategyFactory
{
public static Sniffer getInstance(StrategyName choice) {
Strategy strategy = null;
switch (choice) {
case StrategyName.ImplementedStrategy1:
strategy = new ImplementedStrategy1();
break;
case StrategyName.ImplementedStrategy2:
strategy = new ImplementedStrategy2();
break;
case StrategyName.ImplementedStrategy3:
strategy = new ImplementedStrategy3();
break;
}
return strategy;
}
}
现在我怎样才能让这种动态变化?或者为什么我不应该?
答案 0 :(得分:2)
让ImplementedStrategy
合同包含IsGoodMatch(params)
方法。然后,您只需遍历您的策略集合,在每个策略上调用IsGoodMatch
,直到获得一个(或多个)结果,然后使用该策略(ies)。
答案 1 :(得分:1)
我不确定这是否会有所帮助,但这就是我的想法。
public class ImplementedStrategy1 : Strategy
{
}
public class ImplementedStrategy2 : Strategy
{
}
等。
然后你创建一个属性类[StrategyName(StrategyName.EnumValue)]。 更多细节https://msdn.microsoft.com/en-us/library/aa288454(v=vs.71).aspx
所以,现在我们得到了
[StrategyName(StrategyName.EnumValue1)].
public class ImplementedStrategy1 : Strategy
{
}
[StrategyName(StrategyName.EnumValue2)].
public class ImplementedStrategy2 : Strategy
{
}
然后,在公共静态Sniffer getInstance(策略名称选择)而不是交换机中,使用反射,您将获得从策略继承的所有类型,并检查choice参数是否与自定义属性值匹配。
现在您只需要为该类型创建一个新实例。
完成此操作并希望添加新策略后,您只需使用该属性创建新类,并为枚举添加新值。
如果您需要任何实施方面的帮助,请与我们联系。
答案 2 :(得分:1)
不确定是否仍需要此功能,但是可以通过Java如下实现。
public interface Strategy {
boolean isGoodMatch(StrategyName strategyName);
}
public class ImplementedStrategy1 implements Strategy {
@Override
public boolean isGoodMatch(StrategyName strategyName) {
return strategyName == StrategyName.ImplementedStrategy1;
}
}
public class ImplementedStrategy2 implements Strategy {
@Override
public boolean isGoodMatch(StrategyName strategyName) {
return strategyName == StrategyName.ImplementedStrategy2;
}
}
public class ImplementedStrategy3 implements Strategy {
@Override
public boolean isGoodMatch(StrategyName strategyName) {
return strategyName == StrategyName.ImplementedStrategy3;
}
}
public class StrategyFactory {
private List<Strategy> strategies;
public StrategyFactory(List<Strategy> strategies){
this.strategies = strategies;
}
public Strategy getInstance(StrategyName choice){
Strategy strategyChoice = null;
for (Strategy strategy: this.strategies){
if(strategy.isGoodMatch(choice))
strategyChoice = strategy;
}
return strategyChoice;
}
}
如果需要,可以在getInstance方法中使用流。
public Strategy getInstance(StrategyName choice){
return strategies
.stream()
.filter(x -> x.isGoodMatch(choice))
.findFirst()
.get();
}
您可以使用如上所述的DI容器将列表提供给工厂。如果您使用的是类似Spring的工具,则可以使用@Autowire注释。