GeoTools的API系统被其开发者精心的维护者,其保证在更新的过程中尽可能的不改动其API体系,以减少对使用者的影响。并且GeoTool的API在实现库的基础上,被清晰的划分为几组应用编程接口供调用。
一、公共API
作为一个开源库,您可以*调用按时交付应用程序所需的任何 GeoTools 类。
然而,GeoTools 提供了一种干净的方法,随着 GeoTools 的成熟,它应该在库升级期间对您的代码造成最少的中断。
GeoTools 从库的内部实现中干净地分离出几组应用程序编程接口 (API)。
如果您针对这些接口编写代码,它们会在库升级时提供稳定的目标。如果这些接口发生变化(有时我们的标准会发生变化),这些接口将在单个发布周期内被弃用,让您有机会升级。
1.1通常接口来自于三个位置:
- gt-opengis 依据ISO和OGC发布的接口
- jts topology suit Simple Features for SQL(SFSQL) OGC标准的地理实现库
- gt-api GeoTools提供的接口
我们还有一项停滞不前的工作正在进行中:
-
gt-opengis
有一组 ISO19107 几何接口(有人对曲线和 3D 感兴趣吗?)
这些接口代表应用程序中的空间概念和数据结构,适用于方法签名。
1.2工厂类:
GeoTools使用接口来表示数据类型,使用工厂类的create方法来创建数据对象(而不使用new。工厂类使你能够创建各种库需要的数据对象,例如:Features,Styles,Filters,CoordinateReferencingSystems,和DataStores等。另外还提供了一个FactoryFinder类帮助你寻找CLASSPATH上面所有的工厂类。借助于这样的设计,甚至可以仅通过接口就可以实现功能
二、对象的创建
2.1工厂类示例:
Scala允许将构造函数定义在接口中,但是java不能这样,因此为了创建实现(而不是具体的对象),GeoTools采用工厂类来创建实现。GeoTools创建对象的逻辑为:FactoryFinder找到合适的工厂类,使用工厂类创建对象。一个典型的工厂类创建实现的示例如下:
FilterFactory2 factory = CommonFactoryFinder.getFilterFactory2( null ); Filter filter = factory.less( factory.property( "size" ), factory.literal( 2 ) ); if( filter.evaulate( feature )){ System.out.println( feature.getId() + " had a size larger than 2" ); }
2.2工厂类参考:
从上面的示例中,可以看到从工厂类和接口的名字之间有明显的规律:接口比工厂类少了FactoryFinder。
在实际应用中,可以将多个工厂类合并到一个类中来获取所需的工厂类:
CommonFactoryFinder:FilterFactory、StyleFactory、Function、FeatureLockFactory、FileDataStore(文件)、FeatureFactory、FeatureTypeFactory、FeatureCollections
访问feature(例如vector)内容:DataAccessFinder, DataStoreFinder,FileDataStoreFinder
访问coverage(例如raster)信息:GridFormatFinder,CoverageFactoryFinder
JTSFactoryFinder(用于创建JTS GeometryFactory和PercisionModel):GeometryFactory,PrecisionModel
ReferencingFactoryFinder(用于列出参考的工厂类):atumFactory ,CSFactory ,DatumAuthorityFactory ,CSAuthorityFactory , CRSAuthorityFactory ,MathTransformFactory , CoordinateOperationFactory ,CoordinateOperationAuthorityFactory
三、获取工厂类
既然在GeoTools中,工厂类这么重要,那么怎么获得合适的工厂类呢。根据就项目环境的不同,获取的方式也多种多样:
- GeoTools提供的FactoryFinder
- Spring上下文Bean
- JNDI
- 直接使用一个Factory
- 直接new对象
- FactoryFinder:
FactoryFinder是Spring框架下的项目最佳的选择,它是全局唯一的,可以查找可以使用的插件。非Spring项目也可以使用GeoTools提供的FactoryFinder。
FactoryFinder使用了java内置的插件系统,名为工厂服务提供接口(Factory Service Provide Interface)。这个技术允许一个jar指明它创建的哪些服务是可用的(这里是一个工厂接口的各种实现)。
为了便于使用,GeoTools提供了一系列的FactoryFinders。这些类像火柴制造者一样,在CLASSPATH中寻找可用的实现。例如:
FilterFactory filterFactory = CommonFactoryFinder.getFilterFactory( null );
直接使用Factory
例如:
DataStoreFactorySpi factory = new ShapefileDataStoreFactory(); File file = new File("example.shp"); Map map = Collections.singletonMap( "url", file.toURL() ); DataStore dataStore = factory.createDataStore( map );
但是这样的话,你使用了一个具体的类,而不是依靠GeoTools的插件系统来为你寻找一个最佳的实现。
可以为FactoryFinder指定一个线索(Hint)来帮助寻找需要的Factory,例如:
Hints hints = new Hints( Hints.FILTER_FACTORY, "org.geotools.filter.StrictFactory" ); FilterFactory filterFactory = CommonFactoryFinder.getFilterFactory( hints );
直接new对象:
File file = new File("example.shp"); URI namespace = new URI("refractions"); ShapefileDataStore shapefile = new ShapefileDataStore( example.toURL()); shapefile.setNamespace(namespace); shapefile.setMemoryMapped(true);
GeoTools不鼓励,甚至反对这么直接new对象,因为它提高了耦合度,并且不符合插入原则。但是GeoTools并没有把相应接口实现的构造函数生命为private来禁止你直接new对象。GeoTools为了支持这种快速使用的方法,使用了一些额外的方法来处理一些数据例如ShapefileDataStore中的:
shapefile.forceSchemaCRS( CRS.decode( "EPSG:4326" ) );