单例模式的思想简介
单例的基本思维
单例是一种保证对象只有一个的设计模式。
比如数据库连接。如果用hibernate,会在应用初始化时,就创建数据库连接。在访问时通过方法,而不是通过new产生。
对比其他的几种做法:
1在需要时new连接对象,用完后关闭。这样频繁的开和关,效率低。同时代码融入很多无关的成分。
2在初始化时new,放到全局区,比如java web的application context中。这种访问太直接了。
单例的经典实现(代码)
也可以参考这篇文章
http://www.cnblogs.com/BoyXiao/archive/2010/05/07/1729376.html?login=1
单例的本质
1单例是一种保证对象只有一个的设计模式。
2单例的本质在于共享
1并没有说明什么时候该用单例模式,而2则是针对这点的。
共享有两种情况:
由于使用共享的资源(如static,文件等),不得不由共享对象来操作。
某对象比较复杂,不应该每个使用者都创建一个,所以共享。
3单例和全局变量
从使用角度来说,单例和全局变量都是为了共享。但唯有单例才能保证对象只有一个,所以单例和全局变量有所不同。
但有时单例不一定用getInstance的方法实现的。比如说Spring中也把动态生成的对象叫单例,这种单例并没有用单例模式约束的,仅仅就是用户不自己创建,而是使用Spring提供的那个对象(本质上是放在session的全局变量,但也有人叫这种对象单例)
4单例不一定是只有一个的
比如qq软件的登录状态对象,我们希望每个用户在某一时刻只有一个登录状态对象,不可以在两台机子同时上q。那么在服务端就会为每个用户的登录状态建立一个单例。比如
单例的重要概念
1单例的生存周期。单例什么时候会销毁。有的是request级的,有的是session级的,有的是application级的。这主要看单例依赖于什么。比如登录信息放在session中,就会是session基本的。单例常常用static实现,由于static属于类成员,只有在应用停止时才会销毁,所以是application级别的。
2单例与多线程。既然单例共享资源,就一定要考虑多线程问题。对操作共享资源的函数,就要加同步了。百闻不如一见,还是贴一段代码,代码的背景是这样的,数据库中存了树形结构的数据,这个类RoleTree把树结构读出来,缓存到static中。作为一个单例给需要使用这颗树的地方调用。
1 package com.xcat.user; 2 3 import java.sql.Connection; 4 import java.sql.PreparedStatement; 5 import java.sql.SQLException; 6 import java.util.ArrayList; 7 import java.util.HashMap; 8 import java.util.HashSet; 9 import java.util.LinkedList; 10 import java.util.List; 11 import java.util.Map; 12 import java.util.Queue; 13 import java.util.Set; 14 15 import com.xcat.common.DB; 16 17 public class RoleTree { 18 private Map<Integer,Role> treeUp; 19 private Map<Integer,Set<Integer>> treeDown; 20 private static RoleTree instance = null; 21 private RoleDao roleDao; 22 23 private RoleTree() { 24 roleDao = new RoleDao(); 25 reinit(roleDao.list()); 26 } 27 28 public static synchronized RoleTree getInstance() { 29 if (instance == null) { 30 instance = new RoleTree(); 31 } 32 return instance; 33 } 34 35 public void reinit(List<Role> ls){ 36 37 treeUp = new HashMap<Integer,Role>(); 38 treeDown = new HashMap<Integer,Set<Integer>>(); 39 for(Role r : ls){ 40 treeUp.put(r.getId(), r); 41 treeDown.put(r.getId(), new HashSet<Integer>()); 42 } 43 treeDown.put(0,new HashSet<Integer>()); 44 for(Role r : ls){ 45 treeDown.get(r.getParentId()).add(r.getId()); 46 } 47 } 48 49 public synchronized void add(Role r){ 50 roleDao.add(r); 51 r= roleDao.loadByName(r.getName()); 52 treeUp.put(r.getId(), r); 53 treeDown.put(r.getId(), new HashSet<Integer>()); 54 treeDown.get(r.getParentId()).add(r.getId()); 55 56 } 57 58 public void addAsRoot(Role r){ 59 r.setParentId(0); 60 add(r); 61 } 62 63 public void addByParent(Role r,int parentId){ 64 r.setParentId(parentId); 65 add(r); 66 } 67 68 public List<Role> getChildren(int id){ 69 List<Role> ls= new ArrayList<Role>(); 70 Queue<Integer> queue = new LinkedList<Integer>(); 71 queue.offer(id); 72 while (queue.peek()!=null){ 73 int cur=queue.poll(); 74 ls.add(treeUp.get(cur)); 75 Set<Integer> set=treeDown.get(cur); 76 if(set!=null) 77 for(int i : set) queue.offer(i); 78 } 79 80 for(Role r : ls) 81 if(r.getId()==0) { 82 ls.remove(r); 83 break; 84 } 85 86 return ls; 87 } 88 89 public List<Role> list(){ 90 List<Role> ls= new ArrayList<Role>(); 91 for(Role r : treeUp.values()){ 92 ls.add(r); 93 } 94 95 for(Role r : ls) 96 if(r.getId()==0) { 97 ls.remove(r); 98 break; 99 } 100 101 return ls; 102 } 103 104 public Role loadById(int id) { 105 Role r; 106 if(treeUp.containsKey(id)) r=treeUp.get(id); 107 else r=null; 108 return r; 109 } 110 111 public List<Object[]> getIndentName(){ 112 List<Object[]> ls= new ArrayList<Object[]>(); 113 for(int i : treeDown.get(0)) _getInent(ls,i,0); 114 return ls; 115 } 116 117 private void _getInent(List<Object[]> ls, int cur ,int level){ 118 119 Object[] objs =new Object[2]; 120 objs[0]=treeUp.get(cur).getId(); 121 String name=""; 122 for(int i=0;i<level;i++) name+="-"; 123 objs[1]=name+treeUp.get(cur).getName(); 124 ls.add(objs); 125 126 for(int i : treeDown.get(cur)) 127 _getInent(ls,i,level+1); 128 } 129 130 private void showTreeDown(){ 131 for(int key : treeDown.keySet()) { 132 for(int i : treeDown.get(key)) System.out.print(i+","); 133 System.out.println(""); 134 } 135 } 136 137 public synchronized void update(Role r) { 138 roleDao.update(r); 139 140 int oldId=treeUp.get(r.getId()).getParentId(); 141 treeDown.get(oldId).remove(r.getId()); 142 treeUp.remove(r.getId()); 143 144 treeUp.put(r.getId(), r); 145 treeDown.get(r.getParentId()).add(r.getId()); 146 } 147 148 public synchronized void updateParent(int id , int parentId) { 149 roleDao.updateParent(id, parentId); 150 151 int oldId=treeUp.get(id).getParentId(); 152 treeDown.get(oldId).remove(id); 153 154 treeUp.get(id).setParentId(parentId); 155 treeDown.get(parentId).add(id); 156 } 157 158 public void delete(Role r) { 159 deleteById(r.getId()); 160 } 161 162 public synchronized boolean deleteById(int id) { 163 if(treeDown.get(id).size()!=0) return false; 164 165 roleDao.deleteById(id); 166 167 int oldId=treeUp.get(id).getParentId(); 168 treeUp.remove(id); 169 treeDown.get(oldId).remove(id); 170 treeDown.remove(id); 171 return true; 172 } 173 174 public synchronized void deleteBranch(int id) { 175 List<Role> ls=getChildren(id); 176 System.out.println("size:"+ls.size()); 177 List<Integer> lsi=new ArrayList<Integer>(); 178 for(Role r : ls) lsi.add(r.getId()); 179 roleDao.deletebyIds(lsi); 180 181 reinit(roleDao.list()); 182 } 183 }
类关系(类图)
参考文章:http://blog.csdn.net/hguisu/article/details/7515416