`
wenqxin
  • 浏览: 14152 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

由数据库连接所联想到的5种设计模式

阅读更多
     最近在看设计模式方面的资料.突发灵感,从数据库的连接中联想到了5种设计模式.然后编写了下,都能实现,可能有些实现方式在实际生产环境中并没有意义.就当是对设计模式的学习吧.
     首先上演的就是策略模式.我们在连接数据库时,并非一种数据库,比如,有时是MySql,有时是Oracle,有时又换到SQL Server,都要涉及数据库的切换.此时.我们就可以将数据库连接的算法封装起来,使它们可以相互替换.
     首先我们定义一个策略接口,用来表示数据库的连接.
package strategy;

public interface Strategy {

	public void getConnDB();

}

     然后我们实现了对具体的策略类:三大数据库的连接.我们在这里只是强调模式的实现,简单起见,不实现JDBC的连接的具体操作.下面的也是一样.
Mysql:
public class MysqlStrategy implements Strategy {
	public void getConnDB() {
		/*try {
			Class.forName("com.mysql.jdbc.Driver").newInstance();
			String url = "jdbc:mysql://localhost/myDB?user=root&password=123456&useUnicode=true&characterEncoding=utf-8";
			Connection connection = DriverManager.getConnection(url);
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}*/
		System.out.println("connect MySQL");
	}
}

Oracle:
public class OracleStrategy implements Strategy {
	
	public void getConnDB(){
		
		System.out.println("connect  oracle");
		
	}

}

SQL Server:
public class SQLStrategy  implements Strategy{
	public void getConnDB(){
			System.out.println("connect  SQL SERVER");
		}
	}

策略应用场景,方便在运行时动态选择具体要执行的行为.
public class ClientContext {
	Strategy strategy;
	
	public ClientContext(Strategy strategy){
		
		this.strategy=strategy;
	}
	
	public void getConnDB(){
		strategy.getConnDB();
	}

}

下面就开始测试了:
public class StrategyTest {
	public static void main(String[] args) {
		/**
		 * 策略模式实现对Oracle的连接操作.
		 */
		ClientContext occ = new ClientContext(new OracleStrategy());
		occ.getConnDB();
		/**
		 * 策略模式实现对Mysql的连接操作.
		 */
		ClientContext mcc = new ClientContext(new MysqlStrategy());
		mcc.getConnDB();
		/**
		 * 策略模式实现对SQL Server的连接操作.
		 */
		ClientContext scc = new ClientContext(new SQLStrategy());
		scc.getConnDB();

	}

}

    这样,就基本完成通过策略模式动态切换数据库连接的算法.如果想实现对DB2,Sybase,PostgreSQL数据库的操作.只需实现策略接口即可.这样就可以任意扩展.同时对客户(StrategyTest 类)隐藏具体策略(算法)的实现细节,彼此完全独立。完全做到高内聚,低耦合.

     到这里,突然改变需求,需要在数据库连接之前增加一些日志的打印输出.按照传统的做法,我们修改每一个具体的实现类,增加这些功能,如果先前我们实现的具体类非常多.这无异是一笔不小的负担.而且也违反了开闭原则(OCP).
    这里大家可能想到在学习Spring AOP常提到的用AOP打印日志的情景.AOP主要用到了代理模式.这里我们也通过代理模式来实现.由于抽象策略类是接口,所以我们采用JAVA 反射中提供的代理.
   代理模式具体实现:
public class ProxyDB implements InvocationHandler {

	private Object target;

	public ProxyDB(Object target) {
		this.target = target;
	}

	/**
	 * 此处为我们要额外添加的方法 进行日志的打印输出
	 */
	public void printLog() {
		System.out.println("---------------打印输出点日志----------");
	}

	/**
	 * 代理业务处理器
	 */
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Exception {
		printLog();
		return method.invoke(this.target, args);
	}

	public static void main(String[] args) {
		/**
		 * 
		 * 通过代理模式在连接Mysql前增加日志的打印输出;
		 * 
		 */
		MysqlStrategy ms = new MysqlStrategy();
		ProxyDB proxyCorps = new ProxyDB(ms);
		Strategy realObject = (Strategy) Proxy.newProxyInstance(ms.getClass()
				.getClassLoader(), ms.getClass().getInterfaces(), proxyCorps);
		realObject.getConnDB();

		/**
		 * 通过代理模式在连接 Oracle前增加日志的打印输出;
		 * 
		 */
		OracleStrategy os = new OracleStrategy();
		ProxyDB proxyCorps1 = new ProxyDB(os);
		Strategy realObject1 = (Strategy) Proxy.newProxyInstance(os.getClass()
				.getClassLoader(), os.getClass().getInterfaces(), proxyCorps1);
		realObject1.getConnDB();

		/**
		 * 通过代理模式在连接 SQL Server前增加日志的打印输出;
		 * 
		 */
		SQLStrategy ss = new SQLStrategy();
		ProxyDB proxyCorps2 = new ProxyDB(ss);
		Strategy realObject2 = (Strategy) Proxy.newProxyInstance(ss.getClass()
				.getClassLoader(), ss.getClass().getInterfaces(), proxyCorps2);
		realObject2.getConnDB();

	}

}

    

    难道只能通过代理来增加日志功能?这时又突然想到装饰者(Decorator),它本来的目的就是对类的实例追加或扩展附加功能.它可以动态的改变一个对象方法的行为.同时也满足设计原则中的开闭原则.
     装饰者模式
(Decorator):
public class Decorator implements Strategy {

	private Strategy strategy;

	public Decorator(Strategy strategy) {
		this.strategy = strategy;
	}

	/**
	 * 额外增加的功能,
	 * 通过装饰者模式动态改变原来对象方法的行为.
	 */
	public void printLog() {
		System.out.println("---------------先打印输出点日志----------");
	}

	public void getConnDB() {
		printLog();
		strategy.getConnDB();
	}

	public static void main(String[] args) {
		
		/**
		 * 在Oracle连接前增加日志的输出
		 */
		Decorator decorator = new Decorator(new OracleStrategy());
		decorator.getConnDB();
		/**
		 * 在Mysql连接前增加日志的输出
		 */
		Decorator decorator1 = new Decorator(new MysqlStrategy());
		decorator1.getConnDB();
		/**
		 * 在Mysql连接前增加日志的输出
		 */
		Decorator decorator2 = new Decorator(new SQLStrategy());
		decorator2.getConnDB();
	}
}

       呵呵, 这里大家可以比较一下代理模式和装饰者模式的区别.

    有时候,为了安全起见,我们并不像暴露每个具体的数据库连接类给客户.减少客户与后台具体类的依赖关系.提高子系统的独立性和可移植性. 这是需要我们提供一个简单接口,统一跟外界打交道.这时,就该我们的门面模式(Facade)上场了.

Facade外观模式
    为子系统中的一组接口提供一个统一接口。Facade模式定义了一个更高层的接口,使子系统更加容易使用。在构建一个层次化的系统的时候,可以使用Facade模式定义系统的每一层的入口,如果层与层之间是相互依赖的,则可以限定他们仅通过Facade进行通信,从而简化了层与层之间的依赖关系。
    同时也实现了软件设计原则中的迪米特法则(LCP).
public class Facade {

	/**
	 *通过连接操作,提供一个统一的接口,统一跟外界打交道
	 *减少对具体实现类的依赖.
	 *
	 */
	public void getConn() {
		OracleStrategy os = new OracleStrategy();
		MysqlStrategy ms =  new MysqlStrategy();
		SQLStrategy ss =    new SQLStrategy();

		os.getConnDB();
		ms.getConnDB();
		ss.getConnDB();
	}

	public static void main(String[] args) {
		
		new Facade().getConn();
	}
}
 


      其实JAVA 中的JDBC数据库连接本身也采用了门面模式.
     最后一个想到的模式那就是模板模式.这个就没有代码了,大家可以参考Spring所提供的jdbc抽象框架.其核心就是JDBC模板.可能与最开始的想法偏离,就当是一种发散性思维吧.
      最后来个简单总结吧,主要实现了五种模式:策略模式,代理模式,装饰者模式,门面模式和模板模式.两大原则:开闭原则和迪米特法则.至于两大原则
    策略模式  :主要强调算法的封装和自由切换.
    代理模式  :为其他对象提供一种代理以控制对这个对象的访问.
    装饰者模式:动态添加一个类的功能,实现比继承更灵活的扩展方式.
    门面模式  :系统对外提供一个统一简单的接口,减少系统间的耦合性.
    模板模式  :将代码的公共行为提取出来,达到复用的目的.
讲得比较简单,就当是抛砖引玉.望大家使劲拍砖.


    
     

  





   




   
分享到:
评论

相关推荐

    mybatis,spring,struts2,Hibernate的联想配置文件

    Struts2是一个基于MVC(Model-View-Controller)设计模式的Java Web框架,用于简化Java Web应用开发。它提供了强大的拦截器机制,可以实现AOP特性,如日志、权限控制等。在联想配置文件中,Struts2的配置可能涉及...

    C++课程设计通信录

    在实现过程中,可以考虑应用设计模式,如工厂模式用于创建Contact对象,策略模式用于不同的搜索策略(按名字、电话等条件),单例模式管理数据库连接等。设计模式的应用可以使代码更加模块化和可扩展。 7. **测试*...

    趣味记忆5大经典的软件架构风格

    软件架构风格是设计大型复杂软件系统时所采用的组织结构或模式,它们为软件开发提供指导原则和可重用的设计模式。以下是对5大经典软件架构风格的详细说明: 1. 数据流风格:这种风格主要关注数据的处理流程,分为...

    模型---数据建模

    3. EAV模型:文档中提到了“Entity-Attribute-Value”(EAV)模型,这是一种常用于处理稀疏数据集的设计模式,适用于产品属性非常多但每个产品并不都需要所有属性的场景。在EAV模型中,实体、属性和值被分开存储在三...

    ASP.NET 程序设计基础篇.rar

    ASP.NET MVC(Model-View-Controller)是一种设计模式,强调分离关注点,提高了代码的可测试性和可维护性。而ASP.NET Core则是跨平台的轻量级框架,支持.NET Core运行时,具备高性能和模块化特性。 在ASP.NET中,...

    联想Android面试题

    ### 联想Android面试题知识点详解 #### 1. Activity 生命周期 - **`onCreate(Bundle savedInstanceState)`**:这是Activity的初始入口点,在此方法中通常进行初始化操作,例如加载布局、绑定视图等。传入的`Bundle...

    联想R680G7安装windows2008stand R2.doc

    确保联想R680G7服务器已关闭并断开所有非必要的电源连接,然后检查硬件配置是否满足Windows Server 2008 R2的最低系统需求,这通常包括足够的内存(至少2GB)、足够的硬盘空间(建议32GB以上)以及兼容的网络适配器...

    用asp.net写的专卖店的页面代码

    在部署过程中,还需要配置正确的环境变量、数据库连接字符串和其他必要的设置。 综上所述,你手头的代码是ASP.NET构建的一个专卖店页面,目前只包含了前端展示部分,要将其转变为一个完整的电商平台,需要添加后端...

    联想服务器R525G3产品介绍定义.pdf

    联想服务器R525 G3是一款专为政府和大中型企业设计的2U双路高性能机架式服务器,集成了最新的技术成果,旨在提供安全可靠的服务。该服务器以全冗余设计增强了系统的可用性,同时优化了能效,实现智能远程监控管理。...

    Java面试题-各大公司

    理解MVC设计模式,掌握如何进行数据库连接与操作,以及了解容器管理的事务处理都是关键。 4. **数据结构与算法**:面试中常会考察数据结构,如数组、链表、栈、队列、集合、映射等,以及排序和查找算法,如冒泡排序...

    基于Android手机的公路客运班次查询系统设计.pdf

    系统设计采用Client/Server模式,客户端运行在Android平台上,利用Java语言进行开发,而服务器端则在Windows Server 2008 R2操作系统上通过Microsoft Visual Studio 2010创建Web Service查询接口,与西安市公路客运...

    计算机辅助创新技术CAI在产品设计过程中的应用研究.docx

    5. 结构创新:涉及到产品的内部构造和组件连接方式,CAI工具可以辅助优化结构设计,确保产品的稳定性和耐用性。 通过CAI技术,概念设计不再仅依赖于个人的灵感,而是转变为一个有组织、系统化的过程。这不仅提升了...

    网络化联想信息检索系统原理与实现 (1998年)

    网络化联想信息检索系统原理与实现主要探讨的是如何在网络环境下实现一种新型的信息检索方式,即联想式检索。这种检索方式旨在模拟人类的联想思维模式,通过对信息块之间的线性和非线性关系的利用,实现动态和连续的...

    飞信客户端代码

    UI设计通常需要遵循MVC(Model-View-Controller)设计模式,分离业务逻辑和视图显示。 7. 异常处理和错误报告:确保程序在遇到问题时能够优雅地处理,减少崩溃的可能性。这部分代码会包含异常捕获和日志记录机制。 ...

    行业文档-设计装置-一种手写简笔字输入方法和系统.zip

    4. **模式匹配与分类**:识别系统运用模式匹配理论,将提取的特征与已知简笔字数据库中的模式进行比较,找出最相似的匹配项,以此确定输入的简笔字。同时,利用机器学习算法,如支持向量机(SVM)或深度学习的卷积神经...

    毕业答辩ppt模板

    - **数据库连接**:利用JDBC(Java DataBase Connectivity)进行数据库连接,确保数据读取与写入的高效性。 - **代码实现**:具体展示了如何通过SQL语句进行数据查询,以及如何处理查询结果。 ### 六、系统意义与...

Global site tag (gtag.js) - Google Analytics