单例模式的思想简介

单例的基本思维

单例是一种保证对象只有一个的设计模式。

比如数据库连接。如果用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。那么在服务端就会为每个用户的登录状态建立一个单例。比如

View Code

单例的重要概念

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

原文地址:https://www.cnblogs.com/deliver/p/4792322.html