设计模式在GIS中的应用

一、设计模式概述

随着面向对象技术的广泛应用,软件复用在越来越多的开发工程中被采用。在研究软件复用的过程中,设计模式的概念被提了出来。所谓设计模式就是一些设计面向对象的软件的经验总结,它的出现可以说是面向对象理论发展的一个重要的里程碑。地理信息系统(GIS)是一种特定而又十分重要的空间信息系统,它是以采集、贮存、管理、处理分析和描述整个或部分地球表面(包括大气层在内)与空间和地理分布有关的数据的空间信息系统。它不仅要处理一般的、规则的属性数据,还要处理海量的、复杂的空间数据,通常是一个复杂而又庞大的系统,开发起来比较耗费时间和财力。因此GIS的重新实现或者重新修改都是一项耗费巨大的工程。在地理信息系统的软件开发中导入设计模式的思想会在提高地理信息系统质量的同时,提高系统的可复用性、可扩充性和可移植性,从而实现降低成本、分享开发经验等目的。在《设计模式—可复用面向对象软件的基础》书中一共提出了23种设计模式。

二、GIS中应用设计模式的必要性

在地理信息系统开发中,为了开发的基础组件可以重用,我们通常是用面向对象的方法封装成类库,然后客户端程序调用。然而,随着当前GIS软件开发日益的复杂化和大型化,如何做到代码重用、类重用以及组件重用是一个严峻的考验。而设计模式可以解决GIS中常见的问题域。

三、常见设计模式在GIS中应用

1、工厂方法模式

定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法(Factory Method)使一个类的实例化延迟到其子类。也叫虚构造器(Virtual Constructor)。

在GIS底层几何对象模型中,通常需要一个几何抽象基类Geometry,从而可以派生出许多具体的实体类,如Point,PolyLine等。当要创建一个Geometry对象时,我们可以用基类的指针实际指向子类,然而,随着类的增多,管理起来就不方便。这时,我们可以通过抽象工厂方法,将创建对象的过程封装在工厂方法中。

2、组合模式

组合模式常用于构成树形的“整体-部分”之间的关系。在GIS中,地理事物常被抽象为点、线和面三种基本类型。线由点构成,面由首尾相连的线串构成。如下图所示:

3、桥接模式

桥接模式主要是将抽象部分和实现部分分离,对两者进行修改可以独立进行互不依赖。在继承体系中也可以实现这样的操作,那就是模板方法,但是当需求变化时,也会造成类层次的庞大,不利于管理。

在GIS中一个最主要的功能当然是地图的显示了。地图显示过程中通常要用到坐标转换,例如地理坐标和设备坐标之间的转换,这里的设备可以包括计算机屏幕、打印机或者绘图仪等。显示过程中必要要进行放大、缩小、平移等操作。如果将这些操作都写到地图类MAP中,这将会造成地图类的庞大臃肿。如果将这些操作封装在另外一个类DisplayManager中,地图类MAP中保存一个指向DisplayManager类的指针,具体的操作过程交由DisplayManager去完成。下图是具体的类图。

4、模板模式

模板模式最主要的特征是虚基类定义一系列的接口,具体实现的部分交给实体类重写这个方法去完成。例如,在GIS系统中,几何对象模型中就可以用模板方法。虚基类Geometry可以定义一些接口如求面积、长度、绘制等函数。然而,这些函数针对不同的具体类就会有不同的实现,其思想非常简单。

5、命令模式

命令的意图:为一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤消的操作。

在GIS系统中,经常会遇到地理要素的编辑,需要redo/undo。这时就可以向系统发出这些操作的命令,可以先实现一个基类Command,实现逻辑操作接口,然后根据不同的操作去实现真正的操作。它的类图如下。

命令模式还可以和备忘录模式结合完成undo的操作,也就是取消操作。

6、策略模式

策略模式和模板模式解决的问题是相似或者说是相同的。在GIS中,数据类型多种多样,可能会根据应用的需求增加新的数据源。各个数据的数据格式是不一致的,以及他们的原生编程接口也是不一致的。例如shapefile的原生编程接口是shapelib,大名鼎鼎的GDAL/OGR类库就是用这个接口读写shapefile的数据;oracle spatial的C/C++读写接口就是OCI/OCCI。还有各种其他数据,可以说,你就是专做数据格式转换都能将你累垮。如果GIS系统没有考虑到多种格式的需求,那么将来需要应用其他数据格式的时候需要大量改动现有代码的设计,那将是一场灾难,我们并不希望这样。为了能够支持多种数据格式,并对外提供统一的接口支持读写,我们可以采取策略模式。例如对于文件型的数据可以先读取索引文件,然后根据索引文件读写相应位置的几何数据。这样,对外暴漏的接口只要按照接口去存取数据就可以了,而不需要关心数据的底层是如何读写的。当有新的数据类型需要加进来的时候,只需要加入一个对应的新的策略类就可以了。具体的类图如下:

7、单例模式

单例模式可以说是最简单的设计模式,它主要是通过一个类维护一个静态成员变量来记录唯一的对象。在GIS中,由于空间数据类型众多,许多系统针对每一种数据格式都会有一个Driver来读写数据,然而这么多的驱动可以由一个DriverManager来进行方便的管理。在一个系统中,如果驱动管理器很多,这个驱动管理器里面有一个shapefile的驱动,那个驱动管理器里面也有一个shapefile的驱动,这就会造成管理的混乱。所以说,我们要限制驱动的个数为一个就能防止这类问题的发生。

四、后记

当然,本文不可能面面俱到,把23种设计模式如何应用到GIS开发中全部进行讲解不太可能,某些设计模式目前也弄得不是特别明白。欢迎大家一起讨论GIS软件设计中的设计模式,高手就别喷了。

浅谈设计模式在GIS中的应用的更多相关文章

  1. 浅谈surging服务引擎中的rabbitmq组件和容器化部署

    1.前言 上个星期完成了surging 的0.9.0.1 更新工作,此版本通过nuget下载引擎组件,下载后,无需通过代码build集成,引擎会通过Sidecar模式自动扫描装配异构组件来构建服务引擎 ...

  2. 浅谈线程池(中):独立线程池的作用及IO线程池

    原文地址:http://blog.zhaojie.me/2009/07/thread-pool-2-dedicate-pool-and-io-pool.html 在上一篇文章中,我们简单讨论了线程池的 ...

  3. 【ASP.NET MVC系列】浅谈NuGet在VS中的运用

    一     概述 在我们讲解NuGet前,我们先来看看一个例子. 1.例子: 假设现在开发一套系统,其中前端框架我们选择Bootstrap,由于选择Bootstrap作为前端框架,因此,在项目中,我们 ...

  4. 浅谈如何检查Linux中开放端口列表

    给大家分享一篇关于如何检查Linux中的开放端口列表的详细介绍,首先如果你想检查远程Linux系统上的端口是否打开请点击链接浏览.如果你想检查多个远程Linux系统上的端口是否打开请点击链接浏览.如果 ...

  5. 【Unity游戏开发】浅谈Lua和C#中的闭包

    一.前言 目前在Unity游戏开发中,比较流行的两种语言就是Lua和C#.通常的做法是:C#做些核心的功能和接口供Lua调用,Lua主要做些UI模块和一些业务逻辑.这样既能在保持一定的游戏运行效率的同 ...

  6. 浅谈使用spring security中的BCryptPasswordEncoder方法对密码进行加密与密码匹配

    浅谈使用springsecurity中的BCryptPasswordEncoder方法对密码进行加密(encode)与密码匹配(matches) spring security中的BCryptPass ...

  7. Spring源码分析 之浅谈设计模式

    一直想专门写个Spring源码的博客,工作了,可以全身性的投入到互联网行业中.虽然加班很严重,但是依然很开心.趁着凌晨有时间,总结总结. 首先spring,相信大家都很熟悉了. 1.轻量级  零配置, ...

  8. java设计模式学习笔记--浅谈设计模式

    设计模式的目的 编写软件的过程中,程序员面临着来自耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性等多方面的挑战.设计模式为了让程序具有更好的 1.代码重用性(即:相同功能的代码,不用多次编写) ...

  9. 浅谈Observer在代码中表现形式

    说到观察者模式,基本在软件工程领域中是应用广泛,不知道的可以先学习一番,下面给个快速的回顾,然后在通过一个grpc中的responseObserver谈下观察者对象在代码中的位置. 喜欢类图,就不上其 ...

随机推荐

  1. Nubiers to follow

    VGG Andrea Vedaldi Berkeley Trevor Darrell Jeff Donahue Ross Girshick Sergio Guadarrama Stanford And ...

  2. 整理SQL

    由4张简单的不能再简单的表,演变出50道SQL 表结构: 表Student (S#,Sname,Sage,Ssex) 学生表 S#  student_no Sage  student_age   Ss ...

  3. select2使用详解

    官网: https://select2.github.io/examples.html 引用: <link href="~/Scripts/select2/select2.css&qu ...

  4. ActionSupport.getText()方法 以及 js中:<s:text name="" />

    下面略述com.opensymphony.xwork2.ActionSupport.getText()方法 public String getText(String aTextName) 说明:Get ...

  5. fitness

    大家一定要小心那些有6块腹肌的男人和永远保持好身材的女人 这些人拥有你所想不到的决心和意志力 还要小心那些冬天里 能唰的一下起床的人 他们什么事都能干的.

  6. 【3】python核心编程 第五章-数字

    1.用大写字母 “L”表示长整数 尽管 Python 也支持用小写字母 L 标记的长整型,但是我们郑重推荐您仅使用大写的 “L”, 这样能有效避免数字1 和小写L 的混淆.Python 在显示长整数类 ...

  7. NET Core的知识

    NET Core的基础知识补遗 阅读目录 前言 在.NET Core之前 在.NET Core起步 .NET Core 1.0 .NET平台 开发环境 FAQ 写在最后 回到目录 前言 .NET Co ...

  8. SQL查询 addScalar()或addEntity()

    Hibernate除了支持HQL查询外,还支持原生SQL查询.   对原生SQL查询执行的控制是通过SQLQuery接口进行的,通过执行Session.createSQLQuery()获取这个接口.该 ...

  9. Why Does Qt Use Moc for Signals and Slots(QT官方的解释:GUI可以是动态的)

    GUIs are Dynamic C++ is a standarized, powerful and elaborate general-purpose language. It's the onl ...

  10. java设计模式--创建模式--工厂方法

    工厂方法定义: 工厂方法 概述 定义一个用于创建对象的接口,让子类决定实例化哪一个类.FactoryMethod使一个类的实例化延迟到其子类. 适用性 .当一个类不知道它所必须创建的对象的类的时候. ...