前言
使用GeoTools开发时有必要了解其工厂设计模式,作为软件开发核心设计模式,其设计思想具有普遍性和研究性。明白方法原理有助于提高开发效率,达到事半功倍的效果。
1. 工厂模式
工厂模式(Factory Pattern)是面向对象中编程中最常用的设计模式之一,使用工厂不仅可以批量创建对象,而且创建对象的过程与使用对象的过程分离。有利于降低代码的耦合度。
GeoTools的设计也采用了工厂设计模式的思想,用于创建地理空间数据处理中的各种对象。使得其面对各种地理数据格式时,可以灵活拓展。
下面介绍以下GeoTools中常见的工厂模型,主要包括数据存储工厂、几何对象工厂以及坐标系工厂等。
2. 数据存储工厂
GeoTools 数据存储工厂非常丰富,主要包括数据库存储工厂和文件存储工厂两大类,基本都存储处 org.geotools.data
目录下。
(1)DataStoreFactory可以用于连接各种数据源,如数据库和文件。
- 连接数据库:
// 连接PostGIS数据库
Map<String, Object> pgParams = new HashMap<>();
pgParams.put(PostgisNGDataStoreFactory.DBTYPE.key, "postgis");
pgParams.put(PostgisNGDataStoreFactory.HOST.key, "localhost");
pgParams.put(PostgisNGDataStoreFactory.PORT.key, "5432");
pgParams.put(PostgisNGDataStoreFactory.DATABASE.key, "geodata");
pgParams.put(PostgisNGDataStoreFactory.USER.key, "postgres");
pgParams.put(PostgisNGDataStoreFactory.PASSWD.key, "123456");
pgParams.put(PostgisNGDataStoreFactory.SCHEMA.key, "public"); // 明确指定schema
pgParams.put(PostgisNGDataStoreFactory.EXPOSE_PK.key, true); // 暴露主键// DataStoreFinder 自动发现对应工厂
DataStore pgDataStore = DataStoreFinder.getDataStore(pgParams);
- 连接文件:
String provinceLocation = "E:\data\基础数据\行政区\省级行政区\省级行政区\省.shp";
File file = new File(provinceLocation);// 创建 Shapefile 存储器
Map<String, Object> params = new HashMap<>();
params.put("url", file.toURI().toURL());
params.put("charset", "UTF-8");// DataStoreFinder 自动发现对应工厂
DataStore dataStore = DataStoreFinder.getDataStore(params);
也可以用使用FileDataStore dataStore = FileDataStoreFinder.getDataStore(file);
(2)ShapefileDataStoreFactory用于创建Shapefile
存储器。
// 创建 Shapefile 存储器
Map<String, Object> params = new HashMap<>();
params.put("url", file.toURI().toURL());
params.put("charset", "UTF-8");ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory();
ShapefileDataStore dataStore = (ShapefileDataStore) dataStoreFactory.createDataStore(params);
(3)PostgisNGDataStoreFactory用于创建PostGIS
空间数据库连接。
// 连接PostGIS数据库
Map<String, Object> pgParams = new HashMap<>();
pgParams.put(PostgisNGDataStoreFactory.DBTYPE.key, "postgis");
pgParams.put(PostgisNGDataStoreFactory.HOST.key, "localhost");
pgParams.put(PostgisNGDataStoreFactory.PORT.key, "5432");
pgParams.put(PostgisNGDataStoreFactory.DATABASE.key, "geodata");
pgParams.put(PostgisNGDataStoreFactory.USER.key, "postgres");
pgParams.put(PostgisNGDataStoreFactory.PASSWD.key, "123456");
pgParams.put(PostgisNGDataStoreFactory.SCHEMA.key, "public"); // 明确指定schema
pgParams.put(PostgisNGDataStoreFactory.EXPOSE_PK.key, true); // 暴露主键// DataStoreFinder 自动发现对应工厂
DataStore pgDataStore = DataStoreFinder.getDataStore(pgParams);
if (pgDataStore == null) {PostgisNGDataStoreFactory factory = new PostgisNGDataStoreFactory();if (!factory.canProcess(params)) {System.err.println("数据库参数不满足工厂要求");}if (!factory.isAvailable()) {System.err.println("数据库工厂类不可用");}throw new RuntimeException("数据库连接失败,请检查?");
}
3. 几何对象工厂
GeometryFactory 用来为要素创建几何属性,如点、线、面对象。
GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory(null);
// 构造点
Point point = geometryFactory.createPoint(new Coordinate(longitude,latitude));
4. 坐标系工厂
CRSFactory工厂用于创建坐标参考系统。
// 获取数据源坐标系统
CoordinateReferenceSystem crs = schema.getCoordinateReferenceSystem();// 获取地图坐标系统
CoordinateReferenceSystem mapCrs = map.getCoordinateReferenceSystem();// 定义坐标系统
CoordinateReferenceSystem wgs84 = CRS.decode("EPSG:4326");
5. 样式工厂
StyleFactory工厂用于创建图层样式
StyleFactory style = CommonFactoryFinder.getStyleFactory();
// 创建红色填充
Fill fill = style.createFill(ff.literal(Color.RED));
6. 过滤器工厂
FilterFactory工厂用于创建数据过滤条件,通常用于空间查询
// 创建数据过滤器
FilterFactory factory = CommonFactoryFinder.getFilterFactory(null);
// 获取几何属性字段名称
String geometryPropertyName = featureSource.getSchema().getGeometryDescriptor().getLocalName();Filter filter = null;
switch (queryType.toLowerCase()) {case "intersects":filter = factory.intersects(factory.property(geometryPropertyName),factory.literal(geometry));break;case "contains":filter = factory.contains(factory.property(geometryPropertyName),factory.literal(geometry));break;case "disjoint":filter = factory.disjoint(factory.property(geometryPropertyName),factory.literal(geometry));break;
}