天天看点

设计模式之单例设计模式

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