此模式是服务定位器,命令工厂还是其他什么?

时间:2016-06-29 18:59:41

标签: design-patterns dependency-injection factory service-locator

我有以下类(在JEE中,可以在Spring中类似):

@Singleton
public class MyUnknownPatternClass {
    @Inject @Any Instance<SomeInterface> instances;

    public SomeInterface getMatchingInstance(Object someDiscriminator) {
        for(SomeInterface instance : instances) {
            if(instance.supports(someDiscriminator)) {
                return instance;
            }
        }
        throw new IllegalArgumentException("Could not find a matching instace for " + someDiscriminator.toString());
     }
}

使用依赖注入的发现来定位匹配接口的所有实例,这允许我完全解耦策略和使用它的代码。

例如,对于旅行推销员应用程序,并且我有不同的TransportProvider实现travel(Location l)方法,我的业务逻辑可以专注于遵循常规流程:

Salesman m =...;
Location l =  m.getStartLocation();
TransportProvider t = myUnknownPatternClass.getMatchingInstance(m.getTravelMethod());
for(Location d : m.getDestinationsToVisit())
    l = t.travel(d);
    m.doBusinessHere(l);
}

因此解除了推销员是否通过步行,乘船,乘车或任何其他方式旅行。

我的理解是工厂实际实例化对象。 servicelocator更通用,允许运行时注册,上面的代码似乎都没有。它不是白板模式,因为它只返回单个实例。

然而,这是一个非常有用的模式,并且很好地谈论它。

那是什么呢? 那么什么才是这个班级的正确名称 (即SomeInterfaceLocatorSomeInterfaceFactory)?

编辑: 我发现了https://en.wikipedia.org/wiki/Command_pattern#Java_8 它是命令工厂模式吗?

2 个答案:

答案 0 :(得分:0)

此实现不是Factory,因为它不会创建新实例。

它也不是服务定位器,因为它不是定位服务 - 现在这需要一些解释。

服务定位器应返回不同的接口。您的方法是返回实现单个公共接口的对象。这是服务定位器的签名:

T LocateService<T>() { ... }

这是一个可怕的签名,给全世界的开发人员带来了很多麻烦。问题是这种方法的签名并不能说明消费者可能依赖的对象类型。让我用更长的例子来展示它:

class ServiceLocator {
    T Locate<T>();
}

class Golum {

    ServiceLocator locator;

    Consumer(ServiceLocator depedency) { ... }

    void beNice() {
        Preciousss myPrecious = this.locator.Locate<Previousss>();
        myPrecious.DoMagic();
    }
}

void main() {
    new Golum(new ServiceLocator()).beNice(); // Fails!
}

这段代码是滥用服务定位器所带来的所有邪恶的升华。主要功能是初始化Golum类,但它不知道Golum需要什么。 Golum只需要一个服务定位器,任何服务定位器,然后开始运行。当调用beNice方法时,它会转换传递的特定服务定位器对象根本不知道Preciousss类,然后调用Locate失败。

当一个类未明确声明其依赖关系时,会出现负面结果。如果你看看你的情况,那不是那里发生的事情。您的类依赖于SomeInterface,然后请求解析器对象,该对象也知道SomeInterface。我没有看到那里的负面后果。

在谈论命名时,我可能会选择将某个“定位器”对象称为SomeInterfaceLookup,尽管SomeInterfaceLocator不会比这更糟糕。

答案 1 :(得分:0)

我想我会以(Strategy)Selector作为模式。它不是100官方,而是它的作用 除非有人找到更好的名字,否则它表明它不是服务代理商,它不是工厂,不是命令模式。