模式与框架Java EE设计与开发

上传人:1888****888 文档编号:36144634 上传时间:2021-10-29 格式:DOC 页数:78 大小:525.52KB
收藏 版权申诉 举报 下载
模式与框架Java EE设计与开发_第1页
第1页 / 共78页
模式与框架Java EE设计与开发_第2页
第2页 / 共78页
模式与框架Java EE设计与开发_第3页
第3页 / 共78页
资源描述:

《模式与框架Java EE设计与开发》由会员分享,可在线阅读,更多相关《模式与框架Java EE设计与开发(78页珍藏版)》请在装配图网上搜索。

1、第1页,共78页模式与框架模式与框架JavaJava EEEE设计与开发设计与开发第2页,共78页目录第第1 1章章 模式与框架介绍模式与框架介绍 .2 21.1 什么是模式. 21.2 什么是框架. 31.3 模式与框架的区别.31.4 架构模式. 31.5 Java EE核心模式.41.6 GOF模式. 6第第2 2章章 数据层框架与模式数据层框架与模式 .7 72.1 示例. 72.2 使用模式. 92.3 使用设计原则.162.4 数据层框架.212.5 调用. 29第第3 3章章 业务层框架与模式业务层框架与模式 .3030第第4 4章章 表现层框架与模式表现层框架与模式 .3030

2、第第5 5章章 MVCMVC框架与应用框架与应用 .3131第3页,共78页第第1章章 模式与框架介绍模式与框架介绍1.1 1.1 什么是模式什么是模式模式就是解决问题的方法论。每一种模式都描述了解决某一类问题的最佳方法,至少到目前为止是。模式是理论与实践相结合而总结出来的最有效的解决方案,它将随着技术的发展而不断创新,不断完善,所以旧的模式会发现不再适用,而新的模式会出现。模式在各个应用领域都有,譬如在建筑设计中,模式最为常见。如将门安装在距离墙角落 120 公分处,窗户与栏杆的高度在 90 公分左右,长高宽为 300 的模数等。同理,软件设计中,模式也是层出不穷,大量的架构模式,创建模式,

3、结构模式,行为模式,表现层模式,业务层模式,数据层模式等等。1.2 1.2 什么是框架什么是框架就是一组组件、类或接口构成的半成品,仅完成了某些基本功能,譬如日志,安全性,数据访问等,但需要在此基础上进行业务开发,最终构成一个可用的业务系统。基于框架的开发可以节省大量的精力而致力于系统的业务逻辑设计。 譬如在建筑领域,屋架、梁柱就是一个典型的框架,是一个半成品。屋架的作用是承重,但不能遮风挡雨,必须在上面盖瓦或铺设覆盖物,形成屋顶,才能具备完整的功能;粮柱的其本作用是划分空间、承受垂直与横向的压力,但不具备封闭空间、隔声的效果,尚待在柱间砌筑墙体,在梁间铺设楼板才能居住。在软件开发中,框架仅提

4、供了部分通用的功能,还必须经过业务的填充,才能形成一个功能齐全的业务系统。1.3 1.3 模式与框架的区别模式与框架的区别从规模上讲,模式专注于微观层面的分析与设计,而框架着眼于宏观的构造。从实现的角度看,模式只是一种解决问题的方法,一个解决方案,而框架却是一个实现这种方案的具体的产品,有着实际的功效与作用。从关系上讲,模式是框架的理论基础,多个模式的实现构成了一个框架。框架是模式的具体实现,一个局部或全局的框架,一般都要用到模式。既然是框架,本身就表示它是一种好的通用的产品,怎么体现它是好的呢,模式恰好证明了它是解决某一类问题的最好的解决方案,所以说,没有用到模式的框架,将不是一个良好的可用

5、的框架。1.4 1.4 架构模式架构模式第4页,共78页专注于体系结构宏观的组成与创建,而不注重其细节。譬如建筑设计中常用的体系结构模式有:低层建筑采用砖混结构,中高层采用梁柱框架结构,高层建筑普遍采用钢结构、剪力墙结构、洐架结构。在软件应用领域,架构模式也是丰富多用,主要有以下几种:层次模式:Layers管道和过滤模式:Pipes and Filters代理模式: Broker黑板模式:Blackboard水平-垂直元素模式:Horizontal-Vertical MetadataMVC 模式:主要针对系统或子系统和接口1.5 1.5 JavaJava EEEE核心模式核心模式在 java

6、web 应用与企业应用领域,常用的体系架构是 MVC。而 MVC 正好体现了分层的思想。各层之间的联系与区别如下 图:表示层表示层业务层业务层Model1Model2MVC2MVC数据层数据层MVC我们一般将视图(View)与控制器(Controller)叫做表示层,而模型层太笼统,在实际中,我们将模型层分割为业务层与数据层。其中 v 或 v+m 构成了我们的 model1 架构,v+c+m 构成了 model2 架构,又叫 web MVC 或 mvc2 架构,因为不支持推式。但我们习惯将其称为 MVC 体系架构。Sun java Center 定义了 15 种设计模式,在Core J2ee

7、Patterns书中发表。按照MVC 的分层,在每一层都提出了几种模式,这些模式分别组成各层,最后组成一个完整第5页,共78页的 MVC 框架。这些模式分为:表现层模式,又称 Web 层模式,用于 Web 层的界面与 servlet 开发;业务层模式,又称应用层模式,用于业务逻辑的分层与调用;数据层模式,又称集成层模式,用于数据访问表现层模式表现层模式Intercepting Filter(截获过滤截获过滤)对请求和响应进行截获和过滤,在 Servlet2.3 中已实现的 Filter 功能就是属于此模式。该模式可用于单点登陆,以及登陆过程验证等等。Front Controller(前端控制器

8、前端控制器)Servlet 设计的思想主要是用来调度和转发。即调用模型层的类来处理请求,然后将处理后的信息转发到响应页面进行展示,绝不能将业务逻辑代码堆砌在 servlet 方法中。那么如何能体现 servlet 的这一功能需求呢,前端控制器模式很好的解决了这个问题,在一个项目中,只有一个控制器,它是系统的一个入口,由他调用相应的逻辑 Bean,完成相应的处理工作后,更新视图 View。View Helper(视图帮助器视图帮助器)将表现层和表现层的数据进行分离,将表现层的数据单独封装一层,从而可以更加轻松的在表现层进行处理与传递,而与表现层各层低耦合,这就是 View Helper 模式。C

9、omposite View(复合视图复合视图)页面层内容繁多,如何更有效的组织与重用?复合视图模式将一个复杂的页面拆成多个可重用的页面,各页面在程序调用过程中分别维护和显示,从而减少了前台页面的复杂性,也更容易进行个性化和定制。Dispatcher View(派遣视图派遣视图)类似于 Service to Worker 模式,由 Front Controller 和 View Helper 模式组合而成。Front Controller 接受请求,不进行任何业务逻辑处理,立即重定向到请求的服务页面,由页调用模型层代码进行处理。这个模式在视图中进行请求处理,缺点是不适合大型的复杂的应用程序开发,

10、优点是页面快速响应。Service to Worker(服务(服务/工人)工人)与 Dispatcher View 模式共同的地方是,也是由 Front Controller 和 View Helper 模式组合而成,不同的是,Front Controller 接受请求以后,首先进行任何业务逻辑处理,根据处理结果的不同,而定位到相应的响应视图,适合用于大型的复杂业务逻辑的应用系统。业务层模式业务层模式Business Delegate(业务代理)(业务代理)第6页,共78页如何减少表现层与数据层的耦合问题,业务代理模式将业务逻辑做了封装,同时也将数据层的接口做了进一步抽象,从而缓存了调用逻辑,

11、减少了调用开销。Value Object(值对象)(值对象)如何解决表现层与业务层之间的数据交换,以及层内部的数据交换问题呢?将常用的数据单独封装成一个 javaBean,这样便于传递,也便于取值与设置值。与 Map 接口不同的是,VO 更方便对值进行操作。Value Object Assembler(值对象汇编器)(值对象汇编器)将不同的值对象组装成一个更大的值对象,方便在表现层与数据层之间传递数据。Session Faade该模式提供了下一层接口的一个抽象视图,而不是简单地把下一层的 ApI 直接包装起来。常用在对实体 Bean 的访问中,以及需要开发分布式业务时装封业务逻辑。Compos

12、ite Entity(复合实体)(复合实体)用于 EJB1.1 中封装实体 Bean,已过时。Value List Handler(数值清单处理器)(数值清单处理器)值列表处理器模式创建一个对查询结果集的缓存。调用者向值列表处理器发出请求,值列表处理器返回所需的查询结果。值列表处理器实现了迭代器模式。Service Locator(服务定位器)(服务定位器)封装对 jndi 服务器的访问细节,并且对访问方式提供了一个单一的控制点,利用缓冲,效率更高。数据层模式数据层模式Data Access Object(数据访问对象)(数据访问对象)对数据库实体的访问提供了灵活的调用方式,降低了业务层与数据

13、层之间耦合度。Service Activator(服务激活器)(服务激活器)异步处理同步 EJB 组件。1.6 1.6 GOFGOF模式模式GOF 的设计模式-可复用面向对象软件的基础一书中讲到了 23 种设计模式,可谓是最流行最有影响的设计模式。GOF 不是一个人,而是指四个人。它的原意是 Gangs Of Four,就是“四人帮” ,就是指此书的四个作者:Erich Gamma,Richard Helm,Ralph Johnson,John Vlissides。这些模式分为三大类,创建性、结构性、行为性。创建性模式创建性模式Abstract Factory第7页,共78页BuilderFa

14、ctory MethohdPrototypeSingleton结构性模式结构性模式AdapterBridgeCompositeDecoraterFaadeFlyweightProxy行为性模式行为性模式Chain of ResponsibilityCommandInterpreterIteratorMediatorMementoObserveStateStrategeTemplate MethodVisitor第第2章章 数据层框架与模式数据层框架与模式第8页,共78页有了前面的基础,我们开始一个实际的应用。2.1 2.1 示例示例譬如我们要访问数据库,将一张表的所有记录查询出来。怎么做?我们

15、习惯是写一个javaBean,下面是这个 QueryTable.java 的源码:package org.plat.db;import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import java.util.ArrayList;import java.util.Collection;import java.util.HashMap;import java.util.Map;

16、public class QueryTable public Collection getAll() String driver = com.mysql.jdbc.Driver;String url = jdbc:mysql:/localhost:3306/platDB;Connection conn = null;Statement stmt = null;ResultSet rs = null;String sql = select uid,uname,email from users;Collection coll = new ArrayList();Map map = null;try

17、 Class.forName(driver);conn = DriverManager.getConnection(url,root,);stmt = conn.createStatement();rs = stmt.executeQuery(sql);while(rs.next() map = new HashMap();map.put(uid, rs.getString(1);map.put(uname,rs.getString(2);map.put(email, rs.getString(3);coll.add(map); catch (SQLException e) e.printSt

18、ackTrace(); catch (ClassNotFoundException e) e.printStackTrace();第9页,共78页 finallytryif(rs!=null) rs.close();if(stmt!=null) stmt.close();if(conn!=null) conn.close();catch(SQLException e)return coll;我们看这个类,首先连接数据库,然后执行查询,将每一条记录都封装到一个 map中,再将 map 放在集合中,最后返回一个集合对象 。 这样写有什么不对劲的地方呢?首先看满足面向对象设计吗?我们说对象有三大特征

19、,继承、封装、多态。满不满足封装呢?将多个不同的行为封装在一个对象中,让这个对象庞大而臃肿,其本身就不满足对象的概念。那怎么封装呢?封装就是让具体的对象去做自己该做的事情,而不是大包大揽。很明显,上面的 QueryTable 对象,即做了连接,又做了查询,还做了返回值的封装,封装太多,对象的概念模糊。我们要改变这种封装方式。2.2 2.2 使用模式使用模式VO 模式模式Value object 模式认为,大量分散的数据不利于传输,也不利于对数据进行操纵,必须封装为一个对象用来传值。上面的例子中,users 表的三个字段被封装在 Map 接口中,虽然不影响使用,但缺点有二,一是没有体现对象的封装

20、性,我们不知道 Map 中有什么东西,Map 到底代表了哪一种对象;二是 Map 不利数据的获取与设置。基于 vo 模式,我们添加 org.accp.vo 包,并重新封装 Users 表的这三个字段,类 Users 源代码如下:package org.plat.vo;import java.util.Date;public class Users private int pk1;private String uid;private String uname;private String pwd;private String email;private Date birth;public Dat

21、e getBirth() return birth;第10页,共78页public void setBirth(Date birth) this.birth = birth;public String getEmail() return email;public void setEmail(String email) this.email = email;public int getPk1() return pk1;public void setPk1(int pk1) this.pk1 = pk1;public String getPwd() return pwd;public void s

22、etPwd(String pwd) this.pwd = pwd;public String getUid() return uid;public void setUid(String uid) this.uid = uid;public String getUname() return uname;public void setUname(String uname) this.uname = uname;DAO 模式模式解决了 Map 封装数据的问题之后,我们再看,连接和查询也不应该是同一个对象所做的事情,为什么这么说?一是数据对象访问模式本身说明了数据访问应该是一个专门的对象,它抽象了数据

23、层对表的所有访问接口,专注于对数据表的操作,如增、删、改查,而不管任何其它的业务逻辑,业务层将通过 dao 去访问数据层;二是象 QueryTable这样的类会有很多,基本上一张表会有一个这样的对象,这么多对象将都会有连接数据第11页,共78页库的方法,这本身就不满足对象封装与继承的概念。所以,我们用 dao 模式,再创建一个类,专门处理对 Users 表的操作。类 UsersDao是 DAO 模式的具体实现。而对于取数据库的连接,我们再封装一个类 Connector.java,下面是它们的源代码。Connector.java 的源代码:package org.plat.db;import j

24、ava.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;public class Connector public static Connection getConnection() String driver = com.mysql.jdbc.Driver;String url = jdbc:mysql:/localhost:3306/platDB;Connection conn = nul

25、l;try Class.forName(driver);conn = DriverManager.getConnection(url,root,); catch (SQLException e) e.printStackTrace(); catch (ClassNotFoundException e) e.printStackTrace();return conn;public static void close(ResultSet rs ,Statement stmt, Connection conn) tryif(rs!=null) rs.close();if(stmt!=null) st

26、mt.close();if(conn!=null) conn.close();catch(SQLException e)UsersDao.java的源码:package org.plat.dao;import java.sql.Connection;第12页,共78页import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import java.util.ArrayList;import java.util.Collection;import org.old.db.Connector;im

27、port org.old.vo.Users;public class UsersDao public Collection getAll() Connection conn = null;Statement stmt = null;ResultSet rs = null;String sql = select uid,uname,email from users;Collection coll = new ArrayList();Users u = null;try conn = Connector.getConnection();stmt = conn.createStatement();r

28、s = stmt.executeQuery(sql);while(rs.next() u = new Users();u.setUid(rs.getString(1);u.setUname(rs.getString(2);u.setEmail(rs.getString(3);coll.add(u); catch (SQLException e) e.printStackTrace();finallyConnector.close(rs,stmt,conn);return coll;SingleTon模式模式我们再看 Connector.java,用到了许多静态的方法,这样有什么缺点呢?其实Co

29、nnector 是一个无状态的 javaBean,虽然其方法是静态的,永远只分配同一块内存,但其类本身却是可以实例化成多个对象的,这没有从根本上解决问题。能不能只让这个类只有一个实例,然后让这个唯一的实例去访问它的方法,而不需要第13页,共78页在所有的方法前冠以 static 修饰符呢?答案是 SingleTon(单例)模式,它从结构上规定了这个类只需要有一个实例,从而避免了多个实例实际共享同一个方法而带来的资源消耗,修改后 Connecton.java 源码如下:package org.plat.db;import java.sql.Connection;import java.sql.D

30、riverManager;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;public class Connector private static Connector connector = new Connector();private Connector() public static Connector getInstance() return connector;public Connection getConnection() String driver = com.m

31、ysql.jdbc.Driver;String url = jdbc:mysql:/localhost:3306/platDB;Connection conn = null;try Class.forName(driver);conn = DriverManager.getConnection(url,root,); catch (SQLException e) e.printStackTrace(); catch (ClassNotFoundException e) e.printStackTrace();return conn;public void close(ResultSet rs

32、,Statement stmt, Connection conn) tryif(rs!=null) rs.close();if(stmt!=null) stmt.close();if(conn!=null) conn.close();catch(SQLException e)Thread-Specefic-Storage模式模式第14页,共78页上例中的 Connecton.java 的 getConnection()方法,当 web 层通过 servlet 来调用时,将会暴露多线程的安全问,怎么解决呢?我们可以加上同步关键字 synchronized,但却是以性能的损失为代 价的。Threa

33、d-Specific Storage(线程专门存储)模式认为,即然共用资源困难,干脆不用共享,而为共享的资源专门为每个线程创建一个副本。ThreadLocal 是thread local variable,为每一个使用该变量的线程都提供一个变量值的副本,而不会和其它线程的副本冲突。Connecton.java 进一步优化后的源代码如下:package org.plat.db;import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.SQLException

34、;import java.sql.Statement;public class Connector private static Connector connector = new Connector();private Connector() public static Connector getInstance() return connector;private static final ThreadLocal connThread = new ThreadLocal();public Connection getConnection() Connection conn = (Conne

35、ction) connThread.get();if(conn=null) conn = this._getConnection();connThread.set(conn);return conn;private Connection _getConnection() String driver = com.mysql.jdbc.Driver;String url = jdbc:mysql:/localhost:3306/platDB;Connection conn = null;try Class.forName(driver);conn = DriverManager.getConnec

36、tion(url,root,); catch (SQLException e) 第15页,共78页e.printStackTrace(); catch (ClassNotFoundException e) e.printStackTrace();return conn;public void close(ResultSet rs ,Statement stmt, Connection conn) tryif(rs!=null) rs.close();if(stmt!=null) stmt.close();if(conn!=null) conn.close();catch(SQLExceptio

37、n e)事务事务再看 UsersDao.java 的源码,首先获取连接,然后取出表中所有的记录,最后释放资源关闭连接。乍一看似乎没有什么不妥,其实不然。想象这样一种情况,如果我们再添加二张表,一张是岗位表 duty,另一张是用户与岗位关联的中间表 user_duty。现在要查看用户表 users 找到张三的记录,再将其删除,同时删除用户岗位表 user_duty 中张三的所有岗位。这一系列的操作,其实是一个事务,任何时候,为了保证数据的一致性,要么全部提交成功,要么全部提交失败,不允许出现删除张三失败但删除岗位成功的情况。再看我们的例子,我们的 UsersDao 中的方法都是自己取连接,用完后

38、自己关闭,自产自销,根本不能满足我们的要求,这时候,我们需要将 Connection 中的提交方式改为手动提交,如果成功,提交,否则全部回滚。为了体现面向对象的封装,我们再创建一个事务类,Transaction.java:package org.plat.db;import java.sql.Connection;import java.sql.SQLException;public class Transaction Connection con = null;/* * bool为真表明是自动提交,为假则是有事务需手动提交 */第16页,共78页public Transaction(bool

39、ean bool) try con = Connector.getInstance().getConnection();con.setAutoCommit(bool); catch (SQLException e) e.printStackTrace();public Connection getConn() throws SQLException return con;public void commit() if (con != null)try mit(); catch (SQLException e) e.printStackTrace();public void rollback()

40、 if (con != null)try con.rollback(); catch (SQLException e) e.printStackTrace();public void close() if (con != null)try mit(); catch (SQLException e) e.printStackTrace();2.3 2.3 使用设计原则使用设计原则第17页,共78页IOC原则原则我们再看 org.plat.UsersDao 类,加上事务后,不再担心数据一致性的问题了,连接的获取不再是直接调用 Connector 的 getConnection()方法,而必须从事务

41、中得到。这时又出现问题,怎么获取事务呢?是自己直接 new 一个事务,然后取连接吗?很显然,这还是没有解决事务的问题,即还是自己创建事务取连接,然后关闭事务。同时也违反了IOC(Inverse of Control,控制反转原则) ,即不用关心事务是怎么创建的,谁创建的,我只关心怎么使用事务就行了。而 IOC 有四种方式,此处我们采用 set 方法传递事务。修正后的 UsersDao 源代码如下:package org.plat.dao;import java.sql.Connection;import java.sql.ResultSet;import java.sql.SQLExcepti

42、on;import java.sql.Statement;import java.util.ArrayList;import java.util.Collection;import org.old.db.Connector;import org.old.vo.Users;import org.plat.db.Transaction;public class UsersDao private Transaction transaction;public Transaction getTransaction() return transaction;public void setTransacti

43、on(Transaction transaction) this.transaction = transaction;public Collection getAll() Connection conn = null;Statement stmt = null;ResultSet rs = null;String sql = select uid,uname,email from users;Collection coll = new ArrayList();Users u = null;try conn = getTransaction().getConn();第18页,共78页stmt =

44、 conn.createStatement();rs = stmt.executeQuery(sql);while(rs.next() u = new Users();u.setUid(rs.getString(1);u.setUname(rs.getString(2);u.setEmail(rs.getString(3);coll.add(u); catch (SQLException e) e.printStackTrace();finallyConnector.close(rs,stmt,null);return coll;里氏代换原则里氏代换原则再看上面的 UsersDao 类,发现当

45、有许多表时,基本上是每张表都会有一个对应的dao 类,这样将在每个 dao 类里面都封装了一段共同的代码,即对事务的获取和设置。用里氏代换原则可以解决这个问题,即任何基类可以出现的地方,子类一定可以出现。我们可以将这段共同代码封装成一个基类,让这些 dao 子类去继承。根据以上原则,我们再定义一个 ParentDao,作为所有 dao 的父类,封装事务。ParentDao.javapackage org.plat.dao;import org.plat.db.Transaction;public class ParentDao private Transaction transaction;p

46、ublic Transaction getTransaction() return transaction;public void setTransaction(Transaction transaction) this.transaction = transaction;第19页,共78页ISP 原则原则前面提到,当有多张表时,将会有多个 dao,如此多的 dao,它们都是数据访问对象,都有类似的方法,如增、删、改、查等,能不能抽象出一个共同的接口,便于管理和扩展呢?答案是显而易见的。在抽象成接口时,要有哪些方法,这必须满足 ISP(Interface-Segregation Princip

47、le,接口隔离原则)应尽可能提供小的单独的接口,而不是大的总接口。由 ISP 原则,我们再抽象一个接口,IDao.java,所有的子类 dao 去实现这个接口。package org.plat.dao;import java.sql.SQLException;import java.util.Collection;public interface IDao /* 保存信息*/public boolean save(Object vo) throws SQLException ;/* 由主键或其它字段删除信息*/public boolean delete(Object vo) throws SQ

48、LException;/* 由主键修改信息*/public boolean upd(Object vo) throws SQLException;/* 由主键或其它字段查找用户信息*/public Object find(Object vo) throws SQLException;/* 查找表中所有记录信息*/public Collection findAll() throws SQLException ;多态多态再 看上面的 Idao 接口,我们方法中的参数和返回值都定义为 Object 对象,因为每张表都将有一个对应的 vo,所有的 vo 都是继承 Object 对象,于是我们可以用面向

49、对象的特征之一多态来解决这个共同的传值问题,即特殊动态绑定。第20页,共78页仔细想一想,特殊动态绑定固然解决了传值问题,但也暴露一些隐患。其一,任何类都是 Object 对象,将造成传值时类型错误,编译器检查不到的问题,而这个问题本该在编译时解决。其二,Object 封装的对象层面太抽象,不能一目了然的看出这个参数的用意,也失去了面向对象封装的特性。基于以上观点,我们再封装一个抽象类,让所有的值对象 vo 都去继承这个基类。然后修改 IDao 接口,用这个抽象类去传递参数。ValueObject.javapackage org.plat.vo;import java.io.Serializa

50、ble;public abstract class ValueObject implements Serializableprivate String memo;public String getMemo() return memo;public void setMemo(String memo) this.memo = memo;OCP原则原则再看 org.plat.db 包中的 Connector 类,它主要的方法是 getConnection() ,从数据库中取连接。假设现在需求有了改动,要将 mysql 数据库改为 sqlServer 数据库,我们是不是要改这个方法呢?当然要改,不改数

51、据库都连不上了。修改本身固然没有问题,但是,它显然违反了面向对象的一个核心原则OCP(open close principle,开闭原则) ,对扩展开放,对修改关闭。在前期的设计中,我们应该尽可能的抽象出更多的方法,以便项目的扩展与维护,而不是一有问题就改原来的类与方法,进行重构。既然我们现在就能料到日后可能有多个数据库的问题,这里我们必须要考虑到扩展,怎么去做,抽象类。抽象类是 OCP 原则的体现,我们再定义一个 Connector 的抽象类,将关闭方法提取到这里,Connector.java 源代码如下:第21页,共78页package org.plat.db;import java.sq

52、l.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.Statement;public abstract class Connector public abstract Connection getConnectionFromMysql();public abstract Connection getConnectionFromSqlserver();public void close(ResultSet rs, PreparedStatement pst, Statem

53、ent st, Connection conn) tryif(rs!=null) rs.close();if(pst!=null) pst.close();if(st!=null) st.close();if(conn!=null) conn.close();catch(Exception e) 再写一个子类 ConnectorImpl 去实现 Connector,其中的 getConnectionFromSqlserver()方法可以不实现,待日后扩展用。这样新的需求出现,不需要改动原来的类结构,只需要将方法体补上即可。2.4 2.4 框架框架初步初步将上面的源代码整理,画出它们的 UML

54、图如下:IDao(from dao)UsersDao(from dao)Connector(from db)ConnectorImpl(from db)-$connectorTransaction(from db)ParentDao(from dao)Users(from vo)ValueObject(from vo)从图上可以看出,UserDao 类实现了 IDao 接口并继承了 ParentDao,而 ParentDao 又与事务类 Transaction 单向关联。第22页,共78页UsersDao 又调用 ConnectorImpl,后者与自己自反关联,并且继承了抽象类Connecto

55、r。他们在调用时通过 ValueObject 类来传递参数。Users 类继承了 ValueObject,主要用来封装数据库表的字段,并传递参数。整理它们的源代码,得到如下的清单。清单清单 1:ValueObject.javapackage org.plat.vo;import java.io.Serializable;public abstract class ValueObject implements Serializableprivate String memo;public String getMemo() return memo;public void setMemo(String

56、 memo) this.memo = memo;清单清单 2:Users.javapackage org.plat.vo;import java.util.Date;public class Users extends ValueObjectprivate int pk1;private String uid;private String uname;private String pwd;private String email;private Date birth;public Date getBirth() return birth;public void setBirth(Date bi

57、rth) this.birth = birth;public String getEmail() return email;第23页,共78页public void setEmail(String email) this.email = email;public int getPk1() return pk1;public void setPk1(int pk1) this.pk1 = pk1;public String getPwd() return pwd;public void setPwd(String pwd) this.pwd = pwd;public String getUid(

58、) return uid;public void setUid(String uid) this.uid = uid;public String getUname() return uname;public void setUname(String uname) this.uname = uname;清单清单 3:Connector.javapackage org.plat.db;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.State

59、ment;public abstract class Connector public abstract Connection getConnectionFromMysql();public abstract Connection getConnectionFromSqlserver();public void close(ResultSet rs, PreparedStatement pst, Statement st, Connection conn) 第24页,共78页tryif(rs!=null) rs.close();if(pst!=null) pst.close();if(st!=

60、null) st.close();if(conn!=null) conn.close();catch(Exception e) 清单清单 4:ConnectorImpl.javapackage org.plat.db;import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;public class ConnectorImpl extends Connectorprivate s

61、tatic ConnectorImpl connector = new ConnectorImpl();private ConnectorImpl() public static ConnectorImpl getInstance() return connector;private static final ThreadLocal connThread = new ThreadLocal();public Connection getConnection() Connection conn = (Connection) connThread.get();if(conn=null) conn

62、= this.getConnectionFromMysql();connThread.set(conn);return conn;public void close(ResultSet rs ,Statement stmt, Connection conn) tryif(rs!=null) rs.close();if(stmt!=null) stmt.close();if(conn!=null) conn.close();catch(SQLException e)第25页,共78页Overridepublic Connection getConnectionFromMysql() String

63、 driver = com.mysql.jdbc.Driver;String url = jdbc:mysql:/localhost:3306/platDB;Connection conn = null;try Class.forName(driver);conn = DriverManager.getConnection(url,root,); catch (SQLException e) e.printStackTrace(); catch (ClassNotFoundException e) e.printStackTrace();return conn;Overridepublic C

64、onnection getConnectionFromSqlserver() / TODO Auto-generated method stubreturn null;清单清单 5:Transaction.javapackage org.plat.db;import java.sql.Connection;import java.sql.SQLException;public class Transaction Connection con = null;/* * bool为真表明是自动提交,为假则是有事务需手动提交 */public Transaction(boolean bool) try

65、 con = ConnectorImpl.getInstance().getConnection();con.setAutoCommit(bool); catch (SQLException e) e.printStackTrace();public Connection getConn() throws SQLException 第26页,共78页return con;public void commit() if (con != null)try mit(); catch (SQLException e) e.printStackTrace();public void rollback()

66、 if (con != null)try con.rollback(); catch (SQLException e) e.printStackTrace();public void close(Connection conn) if (con != null)try mit(); catch (SQLException e) e.printStackTrace();清单清单 6:ParentDao.javapackage org.plat.dao;import org.plat.db.Transaction;public class ParentDao private Transaction transaction;public Transaction getTransaction() return transaction;第27页,共78页public void setTransaction(Transaction transaction) this.transaction = transaction;清单清单 7:IDao.javapackage org.plat.dao;imp

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!