我有以下类(在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更通用,允许运行时注册,上面的代码似乎都没有。它不是白板模式,因为它只返回单个实例。
然而,这是一个非常有用的模式,并且很好地谈论它。
那是什么呢?
那么什么才是这个班级的正确名称
(即SomeInterfaceLocator
或SomeInterfaceFactory
)?
编辑: 我发现了https://en.wikipedia.org/wiki/Command_pattern#Java_8 它是命令工厂模式吗?
答案 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官方,而是它的作用
除非有人找到更好的名字,否则它表明它不是服务代理商,它不是工厂,不是命令模式。