??xml version="1.0" encoding="utf-8" standalone="yes"?>国产婷婷色一区二区三区在线,欧美日韩综合在线,校园春色亚洲http://www.aygfsteel.com/xixidabao/category/15381.htmlGROW WITH JAVAzh-cnFri, 02 Mar 2007 07:38:10 GMTFri, 02 Mar 2007 07:38:10 GMT60MVC设计模式在通用报表pȝ中的应用 http://www.aygfsteel.com/xixidabao/archive/2006/05/08/45064.htmlJAVA之\JAVA之\Mon, 08 May 2006 10:31:00 GMThttp://www.aygfsteel.com/xixidabao/archive/2006/05/08/45064.html1 引言

  传统报表pȝQ通常是针Ҏ个商业领域用,其用的报表格式往往在设计时p计h员已l定做成模版的Ş式存储在模版库中Q用户用时直接从模版库dQ处理方式也仅限于该领域内;虽然在一定程度上该解x法带来了一定管理上的便宜,可对于现代企业用h_报表格式单一已经局限了报表只能作ؓ记̎来使用Q得报表的可塑性差Q后期维护艰难,难以适应生q程的多h和变化性,无法满大型企业不断扩充的适应性、智能型的要求,特别是当业务领域变化Ӟ原有的报表系l往往很难支持C务数据的理分析Q要q行大量的重新开发工作?/span>

  在本通用报表的设计中Q将报表框架与报表数据分dQ用户即能根据自q需要随意绘制表|又能按照业务要求自主的选择数据来源。一旦框架和数据来源定义完毕Q系l可以自动生成所需要的报表。ؓ了经的辑ֈ方便使用的目的,必须吸收先进的Y件开发思想Q采用优U的Y件开发方法以提高软g质量和Y件的重用性,其中提高软g的重用性是减少开发成本的关键?/span>

  本文主要介绍MVC设计模式在通用报表pȝ开发中的应用,l出了具体问题相应的解决办法Q提高了软g的通用性和扩展性?/span>

2 设计模式

  设计模式是设计面向对象Y件的q程中记录的知识和经验,用一pdcȝ构和对象来具体描q其含义。设计模式的目的是复用q些面向对象设计的解x案,Ҏ具体应用完成具体的设计以及便于这些抽象解x案的U篏和交。与不用设计模式的软gpȝ相比Q一个大量用设计模式的软gpȝ的对象徏模更加合理,对象间的耦合度更,效率、可靠性、可升性、ƈ发性、^行性和分布性更高,更能获得高层ơ的设计复用和代码复用?/span>

  设计模式概念最先来自于城市建筑专家对徏{模式的定义“每一个模式描qC在h们周围不断反复发生的问题Q以及该问题的解x案的核心。这P你就能一ơ又一ơ的使用该方案而不必做重复力_”。这U徏{上的模式思想在面向对象的设计模式中同样适用Q模式的核心在于提供了相关问题的解x案。设计模式确定了所包含的类和实例,它们的角艌Ӏ协作方式以及职责分配。它通过ȝ部g静态和动态结构及其之间的合作关系Q成功地应用于解军_业数据处理、电子通信、图形用L面、数据库、分布式通信软g{Y件构造中的问题?/span>

  一般而言Q设计模式有4个要素:①模式名Uͼ用来描述问题、解x案和效果。②问题Q描q可以在什么时候用设计模式。③解决ҎQ描qC设计模式的组成部分,它们之间的相互关pd各自的职责和协作方式。④效果Q描qC模式应用的效果及使用模式应该权衡的问题。一个设计模式命名抽象确定了一个通用设计l构的主要方面,q些设计l构能用来构造可重用的面向对象设计?/span>

  我们在报表系l中主要使用了模?视图-控制器设计模?MVC)、观察者(ObserverQ、适配器模式(AdapterQ以及桥?Bridge)q几U设计模式?/span>




3 设计模式的应?/strong>

3.1 模型-视图-控制器(MVCQ?/strong>

  报表pȝ中ؓ了方便用户对数据的分析和使用Q同一业务数据常常需要多U视囑֑玎ͼ即一个表格对象和一个柱状图对象可用不同的表示形式描述同一个应用数据对象的消息。表格对象和q对象q不知道Ҏ的存在,q样使用户可以根据需要单独复用表格或q图;当用h变比表格中的信息Ӟq图能立即反映q一变化Q这一行ؓ意味着表格和柱状图都依赖于数据对象。早期的囑Ş化程序设计常常围l着事g驱动的用L面来l织Q这L直接后果是数据处理、程序功能与昄代码完全U结在一赗大型的囑Ş化程序中一个数据通常对应多种表示与处理方式,把特定界面绑定到应用E序上严重降低了E序的灵zL,使得一个很的改动也牵扯到大量的代码,增加了程序开发与l护的工作量?0世纪70q代QMVC模式在small talk 80的GUI设计中被提出Qƈ且描qC不同部分的对象之间的通信方式Q它们不必卷入彼此的数据模型开发方法中QɽE序l构变得清晰而灵zR?/span>

  MVC模式包括三个部分Q模型(ModelQ、视图(ViewQ和控制器(ControllerQ?分别对应于内部数据、数据表C和输入输出控制部分。模型是与问题相x据的逻辑抽象Q代表对象的内在属性,是整个模型的核心。它采用面向对象的方法,问题领域中的对象抽象ؓ应用E序对象Q在q些抽象的对象中装了对象的属性和q些对象所隐含的逻辑。视图是模型的外在表玎ͼ一个模型可以对应一个或者多个视图,如图形用L面视图、命令行视图、API视图Q或按用者分c:新用戯图、熟l用戯囄。视囑օ有与外界交互的功能,是应用系l与外界的接口:一斚w它ؓ外界提供输入手段Qƈ触发应用逻辑q行Q另一斚wQ它又将逻辑q行的结果以某种形式昄l外界。控制器是模型与视图的联pȝ带,控制器提取通过视图传输q来的外部信息,q将用户与View的交互{换ؓZ应用E序行ؓ的标准业务事Ӟ再将标准业务事g解析为Model应执行的动作Q包括激zM务逻辑或改变Model的状态)。同Ӟ模型的更C修改也将通过控制器来通知视图Q从而保持各个视图与模型的一致性?/span>

  实现MVC模式旉对的主要问题是Model和View的关p,在设计模式中的Observer模式很好的描qC如何建立q种关系。这一模式中关键的对象是目标(subjectQ和观察?observer)。一个目标可以有多个依赖它的观察者;一旦目标发生变化,所有依赖它的观察者都得到通知Qƈ做出响应Q即每个观察者都查询目标进行更斎ͼ以保证和目标的状态同步。这U模式允许我们独立的改变目标和观察者;用户可以单独复用目标对象而无需同时复用其观察者,反之亦然。这U模式可以在不改动目标和其他观察者的前提下增加观察者?/span>

  在报表系l中Q目标即Z务数据,观察者定义ؓ在用L面上的显C图。显C图是由其相关的业务数据决定,当业务数据发生变化时Q视图也发生变化。同一业务数据会有多种昄视图Q相同类型的视图也可以表达不同的业务数据。而且可以Ҏ需要在L时刻增加和删除显C图,大大提高了报表系l的通用性?/span>

  当报表系l业务数据变化时Q它要通知依赖它的所有视囑֏生相应的变化Q这样就需要在业务数据对象里记录依赖它的视图,或是增加一个关联查找机制。这两种Ҏ在数据和视图间依赖关pL较少时可以高效的解决问题Q但当它们之间的关系特别复杂Ӟ我们需要一个专门的对象来维护这些关p,q里我们UC为更改管理器QChangeManagerQ,它的目的是尽量减视囑֏映数据变化所需的工作量。例如,如果一个操作涉及到对几个相互依赖的目标q行改动Q就必须保证仅在所有的目标都已l更改完毕后Q才一ơ性的通知它们的观察者,而不是每个目标都通知观察者。另外,观察者ƈ不是Ҏ有的事g都感兴趣Q可以扩展目标的注册接口Q让个观察者注册ؓ仅对特定事g感兴,以提高更新的效率。当一个事件发生时Q目标仅通知那些已注册ؓ对该事g感兴的观察者?/span>

  Observer模式在报表系l中的层ơ结构如?所C,其中DataEntryZ务数据抽象,它的具体实现由ConcreteDataEntry来完成;UserView是显C囄抽象Q具体用的视图由ConcreteUserView实现Q更改管理器QChangeManageQ的实现有两U:SimpleChangeManage和DAGChangeManage Q它们分别管理单一目标的目标—观察者关pd多目标相互关联的目标—观察者关pR?/span>

? 报表pȝ中Observer模式层次l构?/p>

其中业务数据的类定义如下Q?br />
  class DataEntry{
  public :
  virtual ~DataEntry();
  virtual void Attach(UserView *pView ); //增加视图
  virtual void Detach(UserView *pView); //删除视图
  virtual void Notify(UserView *pSender); //通知
  protected:
  DataEntry ();
  private:
  List<UserView*> *UserViewList; //记录视图
  }
  昄视图的定义ؓQ?br />  class UserView{
  public:
  DataEntry getDataEntry(); /*获取业务数据实体的状态,相当于模式中的GetState()和  SetState()*/
  virtual void Notify (UserView *pView);
  virtual void OnDraw(UserView *pView);
  //设计函数以供重蝲
  protected:
  List<DataEntry*> *DataEntryList;
  //记录业务数据实体
  }

在这里简要说明一下NotifyQ)的实玎ͼ

  void Notify:: DataEntry (UserView *pSender){
  ASSERT(pSender==NULL||*UserViewList.IsEmpty()); //判断视图列表是否为空
  POSITION pos = GetFirstViewPosition ();
  While (pos! = NULL)
  {UserView* pView = GetNextView (pos);
  ASSERT_VAILD (pView);
  if (pView != pUserView)
  pView->Notity ();}

3.2 适配器模式(AdapterQ?/span>

  在许多大型企业及某些行业的局域网或广域网内,׃历史和技术发展的原因存在着多种数据库同时在q行的情况,比如某大型企业、某地区的电力单位或电信公司{,可能正同时在使用着多种数据库(Oracle, DB2, SQL Server, Sybase 或Informix{)。在q样多的数据库ƈ存的环境下,要求能Q意访问到q些数据库,实现多种数据库间的数据{化、资源共享、数据一致性和完整性成为系l开发和应用中一个尤为突出的问题?/span>

  构徏通用的数据库讉K主要是实现对数据源访问的底层操作的封装,而仅仅给出数据读取对象或数据集对象等供商业逻辑层调用,因此采用Adapter模式Q根据不同的数据提供者生相应的数据库连接、数据库命o{数据库对象来实现对低层操作的封装,通过暴露执行数据集对象等上层操作以供其他逻辑层调用?/span>

  Ҏ据库的访问基是基于结构化查询语言QSQLQ,在具体对数据库的讉K中,是通过SQL语句来实现的。采用这U设计模式对数据库进行访问的Ҏ是一U通用讉K技术,卛_用程序可用相同的源代码访问不同类型的数据库,如Sybase, Oracle{?/span>

  Adapter模式是将一个类的接口{换成客户希望的另外一个借口。Adapter模式使得原本׃接口不兼容而不能一起工作的那些cd以一起工作,它又UCؓ“Wrapper”包装器。当要用一个已l存在的c,而它的接口不W合需要,或是创徏一个可以复用的c,该类可以与其它不相关的类或不可预见的cd同工作?/span>

Adapter模式的基本结构图如图2所C:

? Adapter模式的基本结构图

  Adapter模式应用在报表系l中Q模式中Target即ؓ应用E序中数据访问类Q它负责q行数据库的q接、进行数据库操作{等Q模式中的Adaptee为实际存在的各种数据库;在进行系l实现时的主要工作是对不同的数据库编写相应的数据源驱动程序,即编写Adapter?/p>

  应用E序Ҏ据库的访问主要是选择一个数据源q连接它、提交SQL语句以及索结果,除此以外q可以确定ƈ调整驱动E序的性能、浏览数据库~目{等Q应用程序中数据讉Kc通过数据源驱动程序访问不同数据资源中的数据,每个不同的数据资源类型由一个数据源驱动E序支持?/span>

  数据源驱动程序是处理数据讉Kcd象的函数调用Q提交SQLhC个指定的数据元,q把l果q回到应用程序;如果有必要,数据源驱动程序修改一个应用程序请求,以h与相关的DBMS支持的语法一致。每个驱动程序都针对特定的DBMSQ例如,一个Oracle驱动E序不能直接讉KInformix DBMS中的数据。数据源驱动E序展示基础DBMS的能力,他们不能实现DBMS不支持的能力。它q行数据源连接、检查应用程序中的函数错误、初始化事务和把SQL语句提交l执行的数据源。数据源驱动E序必须把应用程序的 SQL修改成针对相应DBMS的SQLQƈ把数据发送到数据源,或从数据源检索数据,包括Ҏ应用E序的指定来转换数据cdQ最后断开与数据源的连接?/p>

  当数据源驱动E序的数量增加,q且处理的事物逐渐复杂Ӟ仅仅用应用程序的数据讉KcLq行驱动E序的管理已大大增加了系l的负担Q我们可以提供一个驱动程序管理器来管理数据源驱动E序。此时应用程序是被连接到驱动E序理器,而不是驱动程序。它使用应用E序传递的q接句柄搜烦目标驱动E序中的函数地址Qƈ通过地址调用那个函数。驱动程序管理器多数只是把函数调用从应用E序传送给正确的驱动程序。驱动程序管理器最l的作用是加载和卸蝲数据源驱动程序,应用E序只加载和卸蝲驱动E序理器。当它要使用一个特D的驱动E序Ӟ它调用驱动程序管理器中的q接函数Qƈ指明一个特D数据源或驱动程序名。用该名称Q驱动程序管理器为驱动程序文件名查询数据源信息,比如SQLSRVR.DLLQ然后它加蝲驱动E序Q保存驱动程序中每个函数的地址Qƈ调用驱动E序中的q接函数Q然后初始化它自己,q连接到数据源。当应用E序使用驱动E序做完工作后,它调用驱动程序管理器中的SQLDisconnect。驱动程序管理其中调用驱动程序中的此函数Q断开与数据源的连接。然而,驱动E序理器重新连接它Ӟ把驱动程序保留在内存中。只有当应用E序释放驱动E序使用的连接,或者用不同的驱动E序q接Qƈ且没有器它连接用此驱动E序Ӟ它才卸蝲驱动E序?/p>

3.3 桥接模式(Bridge)

  Bridge设计模式时对象结构模式的一U,它将抽象部分与实现部分分,使它们能够独立实现。当在一个程序中Q某一个抽象可以由很多实现Ҏ的时候,我们通常是用面向对象中l承的方法来实现q协调这些方法。但是这U承机制有以下不的地方,而用Bridge设计模式都能使这些不_到很好地解决?/span>

  l承机制使客户代码在实现功能的时候涉及到特定的相应^収ͼ与^C生相x,对代码的UL产生很大的困难,但是Bridge设计模式抽象和实现部分攑֜独立的不同层ơ的cȝ构中Q将抽象中与pȝq_相关部分分离开来,同时也降低了实现部分对编译的依赖性,当改变一个实现类Ӟq不需要重新编译抽象部分和它的客户E序?/span>

  我们的报表系l是一个通用pȝQ我们希望这个系l能够支持多H口pȝ。虽然不同的H口pȝ有不兼容的程序设计接口,但是所有的H口pȝȝ来说q是在做同一件事情,我们可以对不同的H口pȝ做一个统一的抽象,在对各窗口系l的实现做一些调_使之W合公共接口?/span>

  我们首先定义一个Windows抽象c,它封装了需要各H口pȝ都要做的一些事情,q且能跨不同的H口pȝ实现。在q个抽象cL供了支持大多数窗口系l的方便接口Q其具体的子cL持用L到的不同U类的窗口,而对不同H口pȝ的实现则由WindowImpcdơ隐藏。WindowImp是一个封装了H口pȝ相关代码的对象的抽象c,Z使报表系l运行于一个特定的H口pȝQ我们用该子pȝ的一个WindowImp子类讄Window对象。这P避免了对H口pȝ的直接依赖,q样可以让WindowscM持相对较而且较稳定,同时q能方便的扩展实现层ơ结构以支持新的H口pȝ?/span>

  Window和WindowImp层次l构之间的关pL下图所C,其中Windows_X即ؓ可以扩展的窗口系l接口?/span>

? Window和WindowImp层次l构

4 l语

  应用设计模式可以使看似复杂的pȝ设计和实现简单化Q设计出来的pȝh灉|、健壮和可复用性强{特点,而且q可以方便开发h员的沟通和交流Q保证Y件开发文档的准确性和易读性,便于代码开发工作。在报表pȝ中引入设计模式,不仅加深了对面向对象思想的认识,而且使得pȝ的设计间接明了,提高了Y件系l的可维护性和伸羃性?/span>

  文章p计模式在通用报表pȝ中的使用q行了一定的研究和探讨。主要就通用报表pȝ中几个关键的通用问题l出了相关的设计模式解决Ҏ。该通用报表的设计ؓ解决集团性企业、政府统计的报表汇d析、预编制、合q报表的解决ҎQ它q可以引入到分销理中,以承担DRPpȝ中时性、非l构化数据的l计dQ根据统计管理对象的不同Q它q能成ؓ|上Zl计、资产管理系l的二次开发^台?/span>






JAVA之\ 2006-05-08 18:31 发表评论
]]>
վ֩ģ壺 | ̩| | Ͼ| | | | | ͨɽ| ӥ̶| | | ̫| ԭ| կ| | | | | | | ߰| | | â| | | | | ԫ| | | | | ֣| ʯ| | | ɽ| ʼ| ػ|