天天看點

設計模式之單例設計模式

SINGLETON(單件)—對象建立型模式

1. 意圖

    保證一個類僅有一個執行個體,并提供一個通路它的全局通路點。

2. 動機

    對一些類來說,隻有一個執行個體是很重要的。雖然系統中可以有許多列印機,但卻隻應該有一個列印假脫機(printer spooler),隻應該有一個檔案系統和一個視窗管理器。一個數字濾波器隻能有一個A / D轉換器。一個會計系統隻能專用于一個公司。

    我們怎麼樣才能保證一個類隻有一個執行個體并且這個執行個體易于被通路呢?一個全局變量使得一個對象可以被通路,但它不能防止你執行個體化多個對象。一個更好的辦法是,讓類自身負責儲存它的唯一執行個體。這個類可以保證沒有其他執行個體可以被建立(通過截取建立新對象的請求),并且它可以提供一個通路該執行個體的方法。這就是S i n g l e t o n模式。

3. 适用性

    在下面的情況下可以使用S i n g l e t o n模式

當類隻能有一個執行個體而且客戶可以從一個衆所周知的通路點通路它時。

當這個唯一執行個體應該是通過子類化可擴充的,并且客戶應該無需更改代碼就能使用一個擴充的執行個體時。

适用場景:

    将來系統是高并發的,比如dbinfo,資料庫資訊放在配置檔案裡面,高并發作用是隻讀取一次配置檔案。

    dbinfo

    servlet

    監聽器

    過濾器

注:request和response不是單例對象。每個人通路的都是同一個servlet,但是不同在于,每個人的請求request是不同的,request對象是servlet容器建立的。request對象跟HTTP請求綁定在一起的,一個HTTP請求綁定一個request。

application是一個全局變量,也是一個單例對象。

4. 結構

<a href="https://s1.51cto.com/wyfs02/M01/A6/6A/wKioL1nOM1OB9SurAAA7t5TBWIk299.png" target="_blank"></a>

5. 參與者

S i n g l e t o n

— 定義一個 I n s t a n c e操作,允許客戶通路它的唯一執行個體。 I n s t a n c e是一個類操作(即

S m a l l t a l k中的一個類方法和C + +中的一個靜态成員函數)。

— 可能負責建立它自己的唯一執行個體。

6. 協作

客戶隻能通過S i n g l e t o n的I n s t a n c e操作通路一個S i n g l e t o n的執行個體。

7.實作

常見單例的兩種寫法:

寫法一:

<code>public</code> <code>class</code> <code>ConnectionFactory {</code>

<code>    </code> 

<code>    </code><code>private</code> <code>static</code> <code>ConnectionFactory factory;                    </code><code>//單例對象</code>

<code>    </code><code>private</code> <code>DbInfo dbinfo;</code>

<code>    </code><code>private</code> <code>ConnectionFactory(DbInfo dbinfo){</code>

<code>            </code><code>this</code><code>.dbinfo = dbinfo;</code>

<code>    </code><code>}</code>

<code>    </code><code>public</code> <code>static</code> <code>ConnectionFactory instance(){</code>

<code>        </code><code>if</code><code>(factory == </code><code>null</code><code>){ </code>

<code>            </code><code>DbInfo dbinfo = DbInfo.instance();</code>

<code>            </code><code>factory = </code><code>new</code> <code>ConnectionFactory(dbinfo);        </code>

<code>        </code><code>}</code>

<code>        </code><code>return</code> <code>factory;</code>

<code>    </code><code>/**</code>

<code>     </code><code>* 打開一個資料庫連接配接</code>

<code>     </code><code>* @return</code>

<code>     </code><code>*/</code>

<code>    </code><code>public</code> <code>DbConnection openConnection(){</code>

<code>        </code><code>DbConnection connection;</code>

<code>        </code><code>if</code><code>(</code><code>this</code><code>.dbinfo.getDriver().equals(</code><code>"oracle"</code><code>)){</code>

<code>            </code><code>connection = </code><code>new</code> <code>OracleConnection(factory);</code>

<code>        </code><code>}</code><code>else</code><code>{</code>

<code>            </code><code>connection = </code><code>new</code> <code>MysqlConnection(factory);</code>

<code>        </code> 

<code>        </code><code>return</code> <code>connection;</code>

<code>    </code><code>}  </code>

<code>}</code>

寫法二:

<code>public</code> <code>class</code> <code>ConnectionFactory2 {</code>

<code>    </code><code>private</code> <code>static</code> <code>ConnectionFactory2 factory;              </code><code>//1.要有單例對象</code>

<code>    </code><code>private</code> <code>ConnectionFactory2(){</code>

<code>    </code><code>static</code><code>{</code>

<code>        </code><code>factory = </code><code>new</code> <code>ConnectionFactory2();</code>

<code>    </code><code>public</code> <code>static</code> <code>DbConnection openConnection(){</code>

<code>        </code><code>DbInfo dbinfo = DbInfo.instance();</code>

<code>        </code><code>if</code><code>(dbinfo.getDriver().equals(</code><code>"oracle"</code><code>)){</code>

<code>        </code><code>return</code> <code>connection;    </code>

線程相關單例寫法:

//餓漢式。(常用)

<code>class</code> <code>Single</code>

<code>{</code>

<code>    </code><code>private</code> <code>static</code> <code>final</code> <code>Single s = </code><code>new</code> <code>Single();</code>

<code>    </code><code>private</code> <code>Single(){}</code>

<code>    </code><code>public</code> <code>static</code> <code>Single getInstance()</code>

<code>    </code><code>{</code>

<code>        </code><code>return</code> <code>s;</code>

//懶漢式(延遲加載單例設計模式)

<code>class</code> <code>Single{</code>

<code>    </code><code>private</code> <code>static</code> <code>Single s = </code><code>null</code><code>;</code>

<code>    </code><code>public</code> <code>static</code>  <code>Single getInstance(){</code>

<code>        </code><code>if</code><code>(s==</code><code>null</code><code>){       </code><code>//多重判斷</code>

<code>            </code><code>synchronized</code><code>(Single.</code><code>class</code><code>){     </code><code>//注意鎖的用法</code>

<code>                </code><code>if</code><code>(s==</code><code>null</code><code>)</code>

<code>                    </code><code>s = </code><code>new</code> <code>Single();</code>

<code>            </code><code>}</code>

單例模式有以下特點:

1、單例類隻能有一個執行個體。

2、單例類必須自己建立自己的唯一執行個體。

3、單例類必須給所有其他對象提供這一執行個體。

8.将資料庫配置檔案(檔案配置,xml配置)内容解析到單例對象中

01.解析配置檔案

    配置檔案

<code>dbURL=jdbc:oracle:thin:</code><code>@10</code><code>.0.</code><code>19.252</code><code>:</code><code>1521</code><code>:orcl</code>

<code>dbDriver=oracle.jdbc.driver.OracleDriver</code>

<code>username=moto</code>

<code>password=</code><code>123456</code>

    單例類

<code>public</code> <code>class</code> <code>DbInfo {</code>

<code>    </code><code>private</code> <code>static</code> <code>DbInfo dbInfo;                      </code><code>//單例對象</code>

<code>    </code><code>private</code> <code>String dbURL;</code>

<code>    </code><code>private</code> <code>String dbDriver;</code>

<code>    </code><code>private</code> <code>String username;</code>

<code>    </code><code>private</code> <code>String password;</code>

<code>    </code><code>private</code> <code>DbInfo(){</code>

<code>    </code><code>public</code> <code>static</code> <code>DbInfo instance() </code><code>throws</code> <code>Exception{</code>

<code>        </code><code>if</code><code>(dbInfo == </code><code>null</code><code>){</code>

<code>            </code><code>dbInfo = </code><code>new</code> <code>DbInfo();</code>

<code>            </code><code>dbInfo.init();</code>

<code>        </code><code>}  </code>

<code>        </code><code>return</code> <code>dbInfo;</code>

<code>     </code><code>* 讀取配置檔案,給屬性初始化</code>

<code>    </code><code>private</code> <code>void</code> <code>init() </code><code>throws</code> <code>Exception {</code>

<code>        </code><code>Properties prop = </code><code>new</code> <code>Properties();</code>

<code>        </code><code>String path = DbInfo.</code><code>class</code><code>.getResource(</code><code>"/"</code><code>).getPath() + </code><code>"db.properties"</code><code>;</code>

<code>        </code><code>prop.load(</code><code>new</code> <code>FileInputStream(</code><code>new</code> <code>File(path)));</code>

<code>        </code><code>this</code><code>.dbDriver = prop.getProperty(</code><code>"dbDriver"</code><code>);</code>

<code>        </code><code>this</code><code>.dbURL = prop.getProperty(</code><code>"dbURL"</code><code>);</code>

<code>        </code><code>this</code><code>.password = prop.getProperty(</code><code>"password"</code><code>);</code>

<code>        </code><code>this</code><code>.username = prop.getProperty(</code><code>"username"</code><code>);</code>

<code>    </code><code>public</code> <code>String getDbURL() {</code>

<code>        </code><code>return</code> <code>dbURL;</code>

<code>    </code><code>public</code> <code>String getDbDriver() {</code>

<code>        </code><code>return</code> <code>dbDriver;</code>

<code>    </code><code>public</code> <code>String getUsername() {</code>

<code>        </code><code>return</code> <code>username;</code>

<code>    </code><code>public</code> <code>String getPassword() {</code>

<code>        </code><code>return</code> <code>password;</code>

02.解析xml檔案

    xml檔案

<code>&lt;?xml version=</code><code>"1.0"</code> <code>encoding=</code><code>"UTF-8"</code><code>?&gt;</code>

<code>&lt;config&gt;</code>

<code>&lt;dbinfo&gt;</code>

<code>   </code><code>&lt;dbUrl&gt;jdbc:oracle:thin:</code><code>@10</code><code>.0.</code><code>19.252</code><code>:</code><code>1521</code><code>:orcl&lt;/dbUrl&gt;</code>

<code>   </code><code>&lt;dbDriver&gt;oracle.jdbc.driver.OracleDriver&lt;/dbDriver&gt;</code>

<code>   </code><code>&lt;username&gt;moto&lt;/username&gt;</code>

<code>   </code><code>&lt;password&gt;</code><code>123456</code><code>&lt;/password&gt;</code>

<code>&lt;/dbinfo&gt;</code>

<code>&lt;DbInfo dbUrl=</code><code>"jdbc:oracle:thin:@10.0.19.252:1521:orcl"</code>  <code>dbDriver=</code><code>"oracle.jdbc.driver.OracleDriver"</code>

<code>       </code><code>username=</code><code>"moto"</code> <code>password=</code><code>"123456"</code><code>&gt;&lt;/DbInfo&gt;</code>

<code>       </code> 

<code>&lt;/config&gt;</code>

<code>public</code> <code>class</code> <code>DbInfo2 {</code>

<code>    </code><code>private</code> <code>static</code> <code>DbInfo2 dbInfo;                      </code><code>//單例對象</code>

<code>    </code><code>private</code> <code>Document document;</code>

<code>    </code><code>private</code> <code>DbInfo2(){</code>

<code>    </code><code>public</code> <code>static</code> <code>DbInfo2 instance() </code><code>throws</code> <code>Exception{</code>

<code>            </code><code>dbInfo = </code><code>new</code> <code>DbInfo2();</code>

<code>        </code><code>String path = DbInfo.</code><code>class</code><code>.getResource(</code><code>"/"</code><code>).getPath() + </code><code>"config.xml"</code><code>;</code>

<code>        </code><code>DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();</code>

<code>        </code><code>DocumentBuilder db = dbf.newDocumentBuilder();</code>

<code>        </code><code>document = db.parse(</code><code>new</code> <code>File(path));                             </code><code>//解析XML檔案  </code>

<code>        </code><code>Node node = document.getElementsByTagName(</code><code>"DbInfo"</code><code>).item(</code><code>0</code><code>);</code>

<code>        </code><code>Element element = (Element)node;</code>

<code>        </code><code>dbURL = element.getAttribute(</code><code>"dbUrl"</code><code>);</code>

<code>        </code><code>dbDriver = element.getAttribute(</code><code>"dbDriver"</code><code>);</code>

<code>        </code><code>this</code><code>.username = element.getAttribute(</code><code>"username"</code><code>);</code>

<code>        </code><code>this</code><code>.password = element.getAttribute(</code><code>"password"</code><code>);</code>

<code>    </code><code>public</code> <code>String getDbURL() {      </code>

<code>/**</code>

<code>* 讀取配置檔案,給屬性初始化</code>

<code>*/</code>

<code>//解析</code>

<code>//&lt;DbInfo dbUrl="jdbc:oracle:thin:@10.0.19.252:1521:orcl"  dbDriver="oracle.jdbc.driver.OracleDriver"</code>

<code>//       username="moto" password="123456"&gt;&lt;/DbInfo&gt;</code>

<code>private</code> <code>void</code> <code>init() </code><code>throws</code> <code>Exception {</code>

<code>    </code><code>String path = DbInfo.</code><code>class</code><code>.getResource(</code><code>"/"</code><code>).getPath() + </code><code>"config.xml"</code><code>;</code>

<code>    </code><code>DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();</code>

<code>    </code><code>DocumentBuilder db = dbf.newDocumentBuilder();</code>

<code>    </code><code>document = db.parse(</code><code>new</code> <code>File(path));                             </code><code>//解析XML檔案  </code>

<code>    </code><code>Node node = document.getElementsByTagName(</code><code>"DbInfo"</code><code>).item(</code><code>0</code><code>);</code>

<code>    </code><code>Element element = (Element)node;</code>

<code>    </code><code>dbURL = element.getAttribute(</code><code>"dbUrl"</code><code>);</code>

<code>    </code><code>dbDriver = element.getAttribute(</code><code>"dbDriver"</code><code>);</code>

<code>    </code><code>this</code><code>.username = element.getAttribute(</code><code>"username"</code><code>);</code>

<code>    </code><code>this</code><code>.password = element.getAttribute(</code><code>"password"</code><code>);</code>

版權聲明:原創作品,如需轉載,請注明出處。否則将追究法律責任

本文轉自 叫我北北 51CTO部落格,原文連結:http://blog.51cto.com/qinbin/1969828