單例的基本思惟html
單例是一種保證對象只有一個的設計模式。java
好比數據庫鏈接。若是用hibernate,會在應用初始化時,就建立數據庫鏈接。在訪問時經過方法,而不是經過new產生。web
對比其餘的幾種作法:sql
1在須要時new鏈接對象,用完後關閉。這樣頻繁的開和關,效率低。同時代碼融入不少無關的成分。數據庫
2在初始化時new,放到全局區,好比java web的application context中。這種訪問太直接了。設計模式
單例的經典實現(代碼)緩存
也能夠參考這篇文章session
http://www.cnblogs.com/BoyXiao/archive/2010/05/07/1729376.html?login=1多線程
單例的本質app
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