如何实现自动查找策略的工厂

时间:2016-10-20 14:42:32

标签: c# oop design-patterns

我问自己这个问题,我还没有想到这个。

我在想什么

当您拥有策略模式时,许多实现也使用工厂模式来检索特定策略。互联网上的大多数工厂示例都使用switch或if语句。当您不经常更改或添加策略时,这非常有效。但是,如果工厂用于动态查找策略并且策略经常更改和添加,该怎么办?那么这是程序员的全职工作。现在我有一种情况,我只想添加一个新的策略而不必更改工厂。换句话说,如何实现工厂模式,以便动态搜索策略。我如何列出所有可用的策略。

问题

当我在互联网上寻找这个时,我找不到一个合适的解决方案。我正在考虑使用反射库来执行此操作,但不建议在我看到的任何地方使用反射。那么如何实现动态工厂呢。或者是否有其他模式用于此目的?

示例

策略: enter image description here

工厂:

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;
    }
}

现在我怎样才能让这种动态变化?或者为什么我不应该?

3 个答案:

答案 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注释。

http://www.baeldung.com/spring-autowire