使用OSGI将不同的提供者和使用者链接到一个使用者



我正在尝试使用OSGI framewrok构建一个天气应用程序。我创建了一个由消费者和提供商组成的国家查找器,以及一个由用户和提供商组成,最后是天气提供商和消费者组成的城市查找器。

  1. 在国家/地区,消费者i允许用户检查某个国家/地区是否可以查看天气
  2. 在城市消费者中,我允许用户检查一个城市是否可以在城市提供商中检查天气。我使用了一个hashmap country作为关键字,city作为值
  3. 在天气包中,一旦消费者被执行,我希望用户能够进入一个城市,并且应该使用上面创建的国家包来检查该国家,如果有国家,接下来应该要求用户输入一个城市。应该使用城市包来检查城市,如果存在这样的城市,最后,天气提供商应该使用该城市并提供天气详细信息

我无法理解如何将天气捆绑包与国家和城市捆绑包联系起来

我认为关键的见解是内聚性。在您的描述中,您混合了应用程序的不同方面。也就是说,你将用户交互(我想要用户…)与寻找特定信息的低级机械细节混合在一起。

OSGi的基本思想是将这些部分分离为服务。该服务提供了一个具有高度内聚性的低级功能。也就是说,它只做一件事。如果你查看事件管理服务,你会发现它确实发布了&订阅这个想法是,您最终会得到不同的服务,它们能很好地完成一件事,而与任何其他服务都没有关系(或耦合)。这种策略允许在许多不同的应用程序中重用它们。一旦你降低了内聚性,你就会发现它们在其他应用程序中变得更难重用。这听起来比实际情况更容易,通常需要一些迭代才能获得真正有凝聚力的服务。

组件是可以提供服务的OSGi。通常,组件使用其他服务。在您的示例中,您可以有一个包含城市的数据库。为了保持组件的内聚性,它不应该直接操作数据库,而应该使用服务。您的组件应该是专家,只在城市中使用,但对数据库内容一无所知。每当您编写一个组件,并意识到您正在编写与城市无关的代码时,请将其委托给另一个服务。还要确保你的数据库服务没有关于城市的线索,它只知道数据库。城市组件有一种很好的简单方式,可以从一个对城市一无所知的组件访问其城市。

如果你这样想,你最终会得到很多毫无作用的服务。你需要一个协调这些服务的地方。这是应用程序。应用程序负责整体功能。它的目的是把所有松散的一端绑在一起。在你的情况下,它会消耗城市、天气和其他服务。它还将与用户进行交互。为了与用户互动,它需要能够搜索一个城市。所以像这样的服务接口会很有用:

public interface Geo {
List<String> countries();
List<String>    cities(String country);
Country         city(String country);
City            city(String city);
}

我正在结合你的城市&乡村发现者,因为我发现他们非常有凝聚力。将它们分解会增加复杂性。这项服务允许我在用户界面上创建一个国家的弹出窗口,我可以从选定的国家选择一个城市。

接下来是气象服务:

public interface Weather {
boolean hasWeather( String country, String city);
Report getShortReport(String country, String city);
}

在选择了一个国家&城市我可以向气象局索取报告。

我在这些接口中使用String的原因是为了防止Geo服务和Weather服务之间的耦合。这是我经常看到的新手犯的主要错误之一。创建城市&然后到处使用的Country类型(或者更糟的是,CityKey),有效地使系统再次成为一个大泥球,在这里,所有东西都被一些类绑定到其他所有东西上,这些类只是充当字符串。

因此,现在应用程序组件可以选择一个GUI(HTML、gogo、Swing、SWT等)。它可以有效地集中在GUI上,低级细节由服务提供商处理。应用程序通常应该是系统中唯一不可重用的组件。如果是,则将其分为可重复使用的零件和特定零件。由于这个组件是不可重用的,所以它是软件中唯一不必关心耦合的地方。

总结。其想法是,如果您查看OGSi应用程序的服务图,它应该非常清楚事情发生的位置,并且应用程序组件(通常不是服务本身)将所有这些联系在一起。

希望这能有所帮助。

捆绑包之间连接的常用方式是OSGi服务。您可以发布带有接口或类的服务。使用者然后可以绑定到接口或类。在最低级别上,这可以使用OSGiAPI来完成,但不建议直接使用它。相反,我建议使用带有注释的声明性服务。

请参阅OSGi途中的微服务示例。

它展示了内部连接以及使用和提供REST服务。

最新更新