1 單例模式確保一個類只有一個執行個體,自行提供這個執行個體並向整個系統提供這個執行個體。
2 特點:
3 1,一個類只能有一個執行個體
4 2,自己建立這個執行個體
5 3,整個系統都要使用這個執行個體
6 例: 在下面的對象圖中,有一個"單例對象",而"客戶甲"、"客戶乙" 和"客戶丙"是單例對象的三個客戶對象。可以看到,所有的客戶對象共用一個單例對象。而且從單例對象到自身的連接線可以看出,單例對象持有對自己的引用。
7
8 Singleton模式主要作用是保證在Java應用程式中,一個類Class只有一個執行個體存在。在很多操作中,比如建立目錄 資料庫連接都需要這樣的單線程操作。一些資源管理員常常設計成單例模式。
9 外 部資源:譬如每台電腦可以有若干個印表機,但只能有一個Printer Spooler,以避免兩個列印工作同時輸出到印表機中。每台電腦可以有若干 個通訊連接埠,系統應當集中管理這些通訊連接埠,以避免一個通訊連接埠被兩個請求同時調用。內部資源,譬如,大多數的軟體都有一個(甚至多個)屬性檔案存放系統 配置。這樣的系統應當由一個對象來管理這些屬性檔案。
10
11 一個例子:Windows 資源回收筒。
12 在整個視窗系統中,資源回收筒只能有一個執行個體,整個系統都使用這個惟一的執行個體,而且資源回收筒自行提供自己的執行個體。因此,資源回收筒是單例模式的應用。
13
14 兩種形式:
15 1,餓漢式單例類
16 public class Singleton {
17
18 private Singleton(){}
19
20 //在自己內部定義自己一個執行個體,是不是很奇怪?
21 //注意這是private 只供內部調用
22
23 private static Singleton instance = new Singleton();
24
25 //這裡提供了一個供外部存取本class的靜態方法,可以直接存取
26 public static Singleton getInstance() {
27 return instance;
28 }
29 }
30
31 2,懶漢式單例類
32
33 public class Singleton {
34
35 private static Singleton instance = null;
36
37 public static synchronized Singleton getInstance() {
38
39 //這個方法比上面有所改進,不用每次都進行產生對象,只是第一次
40
41
42 //使用時產生執行個體,提高了效率!
43 if (instance==null)
44 instance=new Singleton();
45 return instance; }
46
47 }
48
49
50 第二中形式是lazy initialization,也就是說第一次調用時初始Singleton,以後就不用再產生了。
51
52
53 注意到lazy initialization形式中的synchronized,這個synchronized很重要,如果沒有synchronized,那麼使用getInstance()是有可能得到多個Singleton執行個體。
54 一般來說第一種比較安全。
55
56 用單例模式實現的java串連MySql資料庫
57
58 package com.adrop.util;
59
60
61
62 import java.sql.*;
63
64
65
66 public class DBManager {
67
68 //使用者名稱
69
70 private String user = "";
71
72 //密碼
73
74 private String password = "";
75
76 //主機
77
78 private String host = "";
79
80 //資料庫名字
81
82 private String database = "";
83
84 //private DBManager dbm=null;
85
86
87
88 /*
89
90 private String url="jdbc:mysql://"+host+"/"+"useUnicode=true&characterEncoding=GB2312";
91
92 */
93
94 private String url ="";
95
96 private Connection con = null;
97
98
99
100 Statement stmt;
101
102 /**
103
104 * 私人的構造方法,保證外部不能執行個體化,只能由DBManager自己能提供自
105
106 * 己的執行個體,並且只能有一個。
107
108 * 根據主機、資料庫名稱、資料庫使用者名稱、資料庫使用者密碼取得串連。
109
110 * @param host String
111
112 * @param database String
113
114 * @param user String
115
116 * @param password String
117
118 */
119
120 private DBManager(String host, String database, String user, String password) {
121
122
123
124 this.host = host;
125
126 this.database = database;
127
128 this.user = user;
129
130 this.password = password;
131
132 //顯示中文
133
134 this.url = "jdbc:mysql://" + host + "/" + database +
135
136 "?useUnicode=true&characterEncoding=GB2312";
137
138
139
140 try {
141
142 Class.forName("org.gjt.mm.mysql.Driver");
143
144 }
145
146 catch (ClassNotFoundException e) {
147
148 System.err.println("class not found:" + e.getMessage());
149
150 }
151
152
153
154 try {
155
156 con = DriverManager.getConnection(this.url, this.user, this.password);
157
158 //連線類型為ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY
159
160 stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
161
162 ResultSet.CONCUR_READ_ONLY);
163
164 }
165
166 catch (SQLException a) {
167
168 System.err.println("sql exception:" + a.getMessage());
169
170 }
171
172 }
173
174 /**
175
176 * 靜態Factory 方法,來獲得一個DBManager執行個體
177
178 */
179
180 public static DBManager getInstance(String host, String database, String user, String password){
181
182 if(dbm==null){
183
184 dbm=new DBManager(host,database,user,password);
185
186 }
187
188 return dbm;
189
190 }
191
192 /**
193
194 * 返回取得的串連
195
196 */
197
198 public Connection getCon() {
199
200 return con;
201
202 }
203
204 /**
205
206 * 執行一條簡單的查詢語句
207
208 * 返回取得的結果集
209
210 */
211
212 public ResultSet executeQuery(String sql) {
213
214 ResultSet rs = null;
215
216 try {
217
218 rs = stmt.executeQuery(sql);
219
220 }
221
222 catch (SQLException e) {
223
224 e.printStackTrace();
225
226 }
227
228 return rs;
229
230 }
231
232 /**
233
234 * 執行一條簡單的更新語句
235
236 * 執行成功則返回true
237
238 */
239
240 public boolean executeUpdate(String sql) {
241
242 boolean v = false;
243
244 try {
245
246 v = stmt.executeUpdate(sql) > 0 ? true : false;
247
248 }
249
250 catch (SQLException e) {
251
252 e.printStackTrace();
253
254 }
255
256 finally {
257
258 return v;
259
260 }
261
262 }
263
266 }