一个mybatis通用crud的对数据库的CRUD用什么设计模式比较好?

设计模式--单例模式的探究作为对象的创建模式[GOF95],单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类。由定义可以总结出单例模式的要点有三个:一是单例类只能有一个实例;二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。在系统中,线程池、缓存、日志对象、、打印机、显卡的驱动对象常被设计成单例。这些应用都或多或少具有的功能。每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。总之,选择单例模式就是为了避免不一致状态,避免政出多头。虽然从类图上看,单例模式是最简单的设计模式之一,但是真正正确地使用单例模式却不是那么简单的事。 首先看一个经典的单例实现。public class Singleton {
private static Singleton uniqueInstance =
private Singleton() {
// Exists name="code">public class Singleton {
private static Singleton uniqueInstance = new Singleton();private Singleton() {// Exists name="code">public class Singleton {
private static Singleton uniqueInstance =
private Singleton() {
// Exists name="code">public class Singleton {
// volatile is very important
uniqueInstance consistency.
private volatile static Singleton uniqueInstance =
private Singleton() {
// Exists name="code">public class Singleton {
// an inner class holder the uniqueInstance.
private static class SingletonHolder {
static final Singleton uniqueInstance = new Singleton();
private Singleton() {
// Exists name="code">public class RegSingleton {
static private HashMap m_registry = new HashMap();
RegSingleton x = new RegSingleton();
m_registry.put(x.getClass().getName(), x);
protected RegSingleton() {
public static RegSingleton getInstance(String name) {
if (name == null) {
name = "com.patterns.singleton.demos.RegSingleton";
if (m_registry.get(name) == null) {
m_registry.put(name, Class.Name(name).newInstance());
} catch (ClassNotFoundException cnf) {
.out.println("Couldn't find class " + name);
} catch (InstantiationException ie) {
System.out.println("Couldn't instantiate an object of type "+ name);
} catch (IllegalAccessException ia) {
System.out.println("Couldn't access class " + name);
return (RegSingleton) (m_registry.get(name));}}// sub-class implements RegSingleton.public class RegSingletonChild extends RegSingleton {
public RegSingletonChild() {
static public RegSingletonChild getInstance() {
return (RegSingletonChild) RegSingleton
.getInstance("com.patterns.singleton.demos.RegSingletonChild");
public String about() {
return "Hello, I am RegSingletonChild.";
}}在GoF 原始的例子中,并没有getInstance() 方法,这样得到子类必须调用的getInstance(String name)方法并传入子类的名字,因此很不方便。加入getInstance() 方法的好处是RegSingletonChild 可以通过这个方法,返还自已的实例。而这样做的缺点是,由于数据类型不同,无法在RegSingleton 提供这样一个方法。由于子类必须允许父类以构造子调用产生实例,因此,它的构造子必须是公开的。这样一来,就等于允许了以这样方式产生实例而不在父类的登记中。这是登记式单例类的一个缺点。GoF 曾指出,由于父类的实例必须存在才可能有子类的实例,这在有些情况下是一个浪费。这是登记式单例类的另一个缺点。 现在我们已经知道如何实现线程的单例类和如何使用一个注册表去在运行期指定单例类名,接着让我们考查一下如何安排类载入器、处理序列化以及单例模式与ThreadLocal的关系。 ??Classloaders 在许多情况下,使用多个类载入器是很普遍的--包括servlet容器--所以不管你在实现你的单例类时是多么小心你都最终可以得到多个单例类的实例。如果你想要确保你的单例类只被同一个的类载入器装入,那你就必须自己指定这个类载入器;例如: private static Class getClass(String classname)
throws ClassNotFoundException {
ClassLoader classLoader = Thread.currentThread()
.getContextClassLoader();
if (classLoader == null)
classLoader = Singleton.class.getClassLoader();
return (classLoader.loadClass(classname));} 这个方法会尝试把当前的线程与那个类载入器相关联;如果classloader为null,这个方法会使用与装入单例类基类的那个类载入器。这个方法可以用Class.forName()代替。 ??序列化 如果你序列化一个单例类,然后两次重构它,那么你就会得到那个单例类的两个实例,除非你实现readResolve()方法,像下面这样: public class Singleton implements java.io.Serializable {
public static Singleton INSTANCE = new Singleton();
protected Singleton() {
// Exists name="code">import org.hibernate.HibernateEimport org.hibernate.Simport org.hibernate.cfg.C public class HibernateSessionFactory {
private static String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml";
private static final ThreadLocal threadLocal = new ThreadLocal();
private static Configuration configuration = new Configuration();
private static org.hibernate.SessionFactory sessionF
private static String configFile = CONFIG_FILE_LOCATION;
configuration.configure(configFile);
sessionFactory = configuration.buildSessionFactory();
} catch (Exception e) {
System.err.println("%%%% Error Creating SessionFactory %%%%");
e.printStackTrace();
private HibernateSessionFactory() {
public static Session getSession() throws HibernateException {
Session session = (Session) threadLocal.get();
if (session == null || !session.isOpen()) {
if (sessionFactory == null) {
rebuildSessionFactory();
session = (sessionFactory != null) ? sessionFactory.openSession()
threadLocal.set(session);
}// Other methods...}我们知道Session是由SessionFactory负责创建的,而SessionFactory的实现是线程安全的,采用前面提到的“饿汉模式”创建单例。多个并发的线程可以同时访问一个SessionFactory并从中获取Session实例,那么Session是否是线程安全的呢?很遗憾,答案是否定的。Session中包含了操作相关的状态信息,那么说如果多个线程同时使用一个Session实例进行CRUD,就很有可能导致数据存取的混乱,你能够想像那些你根本不能预测执行顺序的线程对你的一条记录进行操作的情形吗?以上使用ThreadLocal模式的解决了这一问题。 只要借助上面的工具类获取Session实例,我们就可以实现线程范围内的Session共享,从而避免了线程中频繁的创建和销毁Session实例。当然,不要忘记在用完后关闭Session。ThreadLocal和线程同步机制相比有什么优势呢?ThreadLocal和 线程同步机制都是为了解决中相同变量的访问冲突问题。在同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量。这时该变量是多个线程共享 的,使用同步机制要求程序慎密地分析什么时候对变量进行读写,什么时候需要锁定某个对象,什么时候释放对象锁等繁杂的问题,和编写难度相对较大。 而ThreadLocal则从另一个角度来解决多线程的并发访问。ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal。 由于ThreadLocal中可以持有任何类型的对象,低版本JDK所提供的get()返回的是Object对象,需要强制类型转换。但JDK 5.0通过泛型很好的解决了这个问题,在一定程度地简化ThreadLocal的使用。概括起来说,对于多线程资源共享的问题,同步机制采用了“以时间换”的方式,而ThreadLocal采用了“以空间换时间”的方式。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,因此可以同时访问而互不影响。ThreadLocal是解决线程安全问题一个很好的思路,它通过为每个线程提供一个独立的变量副本解决了变量并发访问的冲突问题。在很多情况下,ThreadLocal比直接使用synchronized同步机制解决线程安全问题更简单、更方便,且结果程序拥有更高的并发性。ThreadLocal在Spring中发挥着重要的作用,在管理request作用域的Bean、事务管理、任务调度、AOP等模块都出现了它们的身影,起着举足轻重的作用。不过在使用线程池的情况下,使用ThreadLocal应该慎重,因为线程池中的线程是可重用的。原文地址:Java单例模式探究 上传我的文档
 下载
 收藏
该文档贡献者很忙,什么也没留下。
 下载此文档
正在努力加载中...
设计模式在JavaEE 数据持久层的研究与实现
下载积分:500
内容提示:设计模式在JavaEE 数据持久层的研究与实现
文档格式:PDF|
浏览次数:2|
上传日期: 03:04:50|
文档星级:
该用户还上传了这些文档
设计模式在JavaEE 数据持久层的研究与实现
官方公共微信通用权限系统怎么设计
[问题点数:40分]
通用权限系统怎么设计
[问题点数:40分]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
2008年10月 PHP大版内专家分月排行榜第二2008年9月 PHP大版内专家分月排行榜第二2008年4月 PHP大版内专家分月排行榜第二2007年12月 PHP大版内专家分月排行榜第二
2008年10月 PHP大版内专家分月排行榜第二2008年9月 PHP大版内专家分月排行榜第二2008年4月 PHP大版内专家分月排行榜第二2007年12月 PHP大版内专家分月排行榜第二
2009年10月 PHP大版内专家分月排行榜第二2009年9月 PHP大版内专家分月排行榜第二2009年7月 PHP大版内专家分月排行榜第二2008年1月 PHP大版内专家分月排行榜第二2007年8月 PHP大版内专家分月排行榜第二2007年5月 PHP大版内专家分月排行榜第二2007年3月 PHP大版内专家分月排行榜第二
2009年11月 PHP大版内专家分月排行榜第三2007年7月 PHP大版内专家分月排行榜第三2007年4月 PHP大版内专家分月排行榜第三2007年1月 PHP大版内专家分月排行榜第三
2013年5月 总版技术专家分月排行榜第一
2015年12月 总版技术专家分月排行榜第二2014年8月 总版技术专家分月排行榜第二2014年7月 总版技术专家分月排行榜第二2013年6月 总版技术专家分月排行榜第二
2013年5月 总版技术专家分月排行榜第一
2015年12月 总版技术专家分月排行榜第二2014年8月 总版技术专家分月排行榜第二2014年7月 总版技术专家分月排行榜第二2013年6月 总版技术专家分月排行榜第二
2010年3月 PHP大版内专家分月排行榜第三2005年4月 PHP大版内专家分月排行榜第三
2009年10月 PHP大版内专家分月排行榜第二2009年9月 PHP大版内专家分月排行榜第二2009年7月 PHP大版内专家分月排行榜第二2008年1月 PHP大版内专家分月排行榜第二2007年8月 PHP大版内专家分月排行榜第二2007年5月 PHP大版内专家分月排行榜第二2007年3月 PHP大版内专家分月排行榜第二
2009年11月 PHP大版内专家分月排行榜第三2007年7月 PHP大版内专家分月排行榜第三2007年4月 PHP大版内专家分月排行榜第三2007年1月 PHP大版内专家分月排行榜第三
2009年10月 PHP大版内专家分月排行榜第二2009年9月 PHP大版内专家分月排行榜第二2009年7月 PHP大版内专家分月排行榜第二2008年1月 PHP大版内专家分月排行榜第二2007年8月 PHP大版内专家分月排行榜第二2007年5月 PHP大版内专家分月排行榜第二2007年3月 PHP大版内专家分月排行榜第二
2009年11月 PHP大版内专家分月排行榜第三2007年7月 PHP大版内专家分月排行榜第三2007年4月 PHP大版内专家分月排行榜第三2007年1月 PHP大版内专家分月排行榜第三
2009年10月 PHP大版内专家分月排行榜第二2009年9月 PHP大版内专家分月排行榜第二2009年7月 PHP大版内专家分月排行榜第二2008年1月 PHP大版内专家分月排行榜第二2007年8月 PHP大版内专家分月排行榜第二2007年5月 PHP大版内专家分月排行榜第二2007年3月 PHP大版内专家分月排行榜第二
2009年11月 PHP大版内专家分月排行榜第三2007年7月 PHP大版内专家分月排行榜第三2007年4月 PHP大版内专家分月排行榜第三2007年1月 PHP大版内专家分月排行榜第三
2013年1月 PHP大版内专家分月排行榜第三2012年12月 PHP大版内专家分月排行榜第三
本帖子已过去太久远了,不再提供回复功能。使用设计模式构建基于NET的通用数据库访问层使用设计
扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
使用设计模式构建基于NET的通用数据库访问层
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='/DocinViewer-4.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口

我要回帖

更多关于 学习哪些数据库比较好 的文章

 

随机推荐