簡體   English   中英

避免策略設計模式中的服務定位器

[英]Avoid Service locator in strategy design pattern

看看那個偽代碼

class A,B,C implements StrategyInterface
{
    private dep;

    constructor(Dep dep) {
        this->dep = dep;    
    }
}

class StrategyResolver
{
    private locator;

    constructor(ServiceLocator locator) {
        this->locator = locator;
    }
    
    public function resolve(data): StrategyInterface
    {
        if ( xxx ) {
            return locator->get(A);
        } else if ( yyy ) {
            return locator->get(B);
        }
        return locator->get(C);
    }
}

由於服務定位器被認為是反模式,在這種情況下如何避免它? A,B,C可以有各種依賴項,這就是為什么我想使用依賴項注入的所有好處來實例化它。 我也可以注入A,B,C作為StrategyResolver依賴項,但是如果我有 10 個策略呢? StrategyResolver依賴項列表太長。

如果您使用的是 Spring,您可以自動注入某種類型的所有已知 bean:

private final List<StrategyInterface> strategies;

public StrategyResolver(List<StrategyInterface> strategies) {
    this.strategies = strategies;
}

如果這是唯一的構造函數,Spring 將毫無問題地注入實現 StrategyInterface 的所有 bean。 當然,Spring 需要知道這些 bean,例如使用類上的 @Named 注釋:

@javax.inject.Named
public class A implements StrategyInterface {

順便說一句,為什么不將界面命名為“策略”? 'Interface' 后綴並沒有真正添加任何東西。

編輯:要確定應用哪個策略,您可以向 Strategy 接口添加一個方法:

@javax.inject.Named
public class A implements StrategyInterface {

    @Override
    public boolean applies(String data) {
        // just an example
        return "xxx".equals(data);
    }

在 StrategyResolver 中,您將擁有如下代碼:

public StrategyInterface resolve(String data) {
    for(StrategyInterface strategy : strategies) {
        if (strategy.applies(data)) {
            return strategy;
        }
    }
    throw new IllegalArgumentException("No strategy applies for " + data);
}

這里唯一的問題是您必須確保始終適用一種策略。 您甚至可以創建一個始終適用的“DefaultStrategy”,但您必須將其添加為策略列表中的最后一個策略。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM