符合中小企业对网站设计、功能常规化式的企业展示型网站建设
本套餐主要针对企业品牌型网站、中高端设计、前端互动体验...
商城网站建设因基本功能的需求不同费用上面也有很大的差别...
手机微信网站开发、微信官网、微信商城网站...
1. 说明
让客户满意是我们工作的目标,不断超越客户的期望值来自于我们对这个行业的热爱。我们立志把好的技术通过有效、简单的方式提供给客户,将通过不懈努力成为客户在信息化领域值得信任、有价值的长期合作伙伴,公司提供的服务项目有:主机域名、虚拟空间、营销软件、网站建设、秦皇岛网站维护、网站推广。
1)单例模式:确保一个类只有一个实例,自行实例化并向系统提供这个实例
2)单例模式分类此乱:饿单例模式激此(类加载时实例化一个对象给自己的引用),懒单例模式(调用取得实例的方法如getInstance时才会实例化对象)(java中饿单例模式性能优于懒单例模式,c++中森铅档一般使用懒单例模式)
3)单例模式要素:
a)私有构造方法
b)私有静态引用指向自己实例
c)以自己实例为返回值的公有静态方法
2.实例
饿单例模式:
复制代码代码如下:
package com.wish.modedesign;
public class HungrySingleton {
private static HungrySingleton instance = new HungrySingleton();
private HungrySingleton(){
}
public static HungrySingleton getInstance(){
return instance;
}
java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例、饿汉式单例、登记式单例三种。
单例模式有一下特点:
1、单例类只能有一个实例。
2、单例类必须自己自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。
单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。总之,选择单例模式就是为了避免不一致状态,避免政出多头。
首先看一个经典的单例实现。
public class Singleton {
private static Singleton uniqueInstance = null;
private Singleton() {
// Exists only to defeat instantiation.
}
public static Singleton getInstance() {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
// Other methods...
}
Singleton通过将构造方法限定为private避免了类在外部被实例化,在同一个虚拟机范围内,Singleton的唯一实例只能通过getInstance()方法访问。(事实上,通过Java反射机制是能够实例化构造方法为private的类的,那基本上会使所有的Java单例实现失效。此问题在此处不做讨论,姑且掩耳盗铃地认为反射机制不存在。)
但是以上实现没有考虑线程安全问题。所谓线程安全是指:如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安族码全的。或者说:一个类或者程序所提供的接口对于线程来说是原子兆好哪操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题。显然以上实现并不袜闷满足线程安全的要求,在并发环境下很可能出现多个Singleton实例。
//////////////////////////////////////////////////////////////////////
验证单例模式的示例
//////////////////////////////////////////////////////////////////////
public class TestStream {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// 该类只能有一个实例
private TestStream() {
} // 私有无参构造方法
// 该类必须自行创建
// 有2种方式
private static TestStream ts1 = null;
// 这个类必须自动向整个系统提供这个实例对象
public static TestStream getTest() {
if (ts1 == null) {
ts1 = new TestStream();
}
return ts1;
}
public void getInfo() {
System.out.println("output message " + name);
}
public static void main(String[] args) {
TestStream s = TestStream.getTest();
s.setName("张孝祥 1");
System.out.println(s.getName());
TestStream s1 = TestStream.getTest();
s1.setName("张孝祥 2");
System.out.println(s1.getName());
s.getInfo();
s1.getInfo();
if (s == s1) {
System.out.println("创建的是同一个实例");
} else if (s != s1) {
System.out.println("创建的不是同一个实例");
} else {
System.out.println("application error");
}
}
}
////////////////////////////////////////////
单例模式(Singleton) ,属于最常见的设计模式之一,大部分系统都会用到,目的是为了维护系统中唯一的一个实例。
可分为郑猛eager模式,示例代码如下:
Java代码
1.class EagerSingleton{
2. private static final EagerSingleton m_instance = new EagerSingleton();
3. private EagerSingleton(){}
4. public static EagerSingleton getInstance(){
5. return m_instance;
6. }
7.}
class EagerSingleton{
private static final EagerSingleton m_instance = new EagerSingleton();
private EagerSingleton(){}
public static EagerSingleton getInstance(){
return m_instance;
}
}
和 lazy模式,示例代码如下:
Java代码
1.class LazySingleton{
2. private static LazySingleton m_instance = null;
3. private LazySingleton(){}
4. public synchronized static getInstance(){
5. if(m_instance == null){
6. m_instance = new LazySingleton();
7. }
8. return m_instance;
9. }
10.}
class LazySingleton{
private static LazySingleton m_instance = null;
private LazySingleton(){}
public synchronized static getInstance(){
if(m_instance == null){
m_instance = new LazySingleton();
喊枝桥 }
return m_instance;
}
}
java源码中,Runtime.getRuntime()就是单例的一个例子。
单例模式的精神就是整个系统中维护一个实例,推广开来,如果在一个系统搭袜中需要维护多个示例,那么就产生了多例模式(multiton)。
多例模式(Multiton) ,通过聚集对象了保留自身的多个示例,根据客户端的参数返回所需要的实例。
示例代码如下:
Java代码
1.class Multiton{
2. private final int INSTANCE_SIZE = 10;
3. private static Map instances = new HashMap(INSTANCE_SIZE);
4. private String name;
5. private Multiton(){}
6. private Multiton(String name){
7. this.name = name;
8. }
9. public synchronized static getInstance(String name){
10. if(instances.containsKey(name)){
11. return instances.get(name);
12. }
13. else{
14. ins = new Multiton(name);
15. instances.put(name, ins);
16. return ins;
17. }
18. }
19.}
class Multiton{
private final int INSTANCE_SIZE = 10;
private static Map instances = new HashMap(INSTANCE_SIZE);
private String name;
private Multiton(){}
private Multiton(String name){
this.name = name;
}
public synchronized static getInstance(String name){
if(instances.containsKey(name)){
return instances.get(name);
}
else{
ins = new Multiton(name);
instances.put(name, ins);
return ins;
}
}
}
[nextpage]
一个实用的例子就是KeyGenerator, 示例代码如下:
Java代码
1.class KeyGenerator{
2. private final int POOL_SIZE = 20;
3. private static Map instances = new HashMap(16);
4. private KeyInfo keyinfo;
5. private KeyGenerator(){}
6. private KeyGenerator(String keyName){
7. this.keyinfo = new KeyInfo(POOL_SIZE, keyName);
8. }
9. public synchronized static getInstance(String keyName){
10. if(instances.containsKey(keyName)){
11. return (KeyGenerator)instances.get(keyName);
12. }
13. else{
14. keyGen = new KeyGenerator(keyName);
15. instances.put(name, keyGen);
16. return keyGen;
17. }
18. }
19. public synzhronized int getNextKey(){
20. return keyinfo.getNextKey();
21. }
22. }
class KeyGenerator{
private final int POOL_SIZE = 20;
private static Map instances = new HashMap(16);
private KeyInfo keyinfo;
private KeyGenerator(){}
private KeyGenerator(String keyName){
this.keyinfo = new KeyInfo(POOL_SIZE, keyName);
}
public synchronized static getInstance(String keyName){
if(instances.containsKey(keyName)){
return (KeyGenerator)instances.get(keyName);
}
else{
keyGen = new KeyGenerator(keyName);
instances.put(name, keyGen);
return keyGen;
}
}
public synzhronized int getNextKey(){
return keyinfo.getNextKey();
}
}
作为对象的创建模式[GOF ] 单例模式确保某一个类只有一个实例 而且自行实例化并向整个系统提供这个实例 这个类称为单例类
单例模式的要点
单例单例
显然单例模式的要点有三个 一是某各类只能有一个实例 二是它必须自行创建这个事例 三是它必须自行向整个系统提供这个实例 在下面的对象图中 有一个 单例对象 而 客户甲 客户乙 和 客户丙 是单例对象的三个客户对象 可以看到 所有的客户对象共享一个单例对象 而且从单例对象到自身的连接线可以看出 单例对象持有对自己的引用
资源管理
一些资源管理器常常设计成单例模式
在计算机系统中 需要管理的资源包括软件外部资源 譬如每台计算机可以有若干个打印机 但只能有一个Printer Spooler 以避免两个打印作业同时输出到打印机中 每台计算机可以有若干传真卡 但是只应该有一个软件负责管理传真卡 以避免出现两份传真作业同时传到传真卡中的情况 每台计算机可以有若干通信端口 系统应当集中管理这些通信端口 以避免一个通信端口同时被两个请求同时调用
需要管理的资源包括软件内部资源 譬如 大多数的软件都有一个(甚至多个)属性(properties)文件存放系统配置 这样的系统应当由一个对象来管理一个属性文件
需要管理的软件内部资源也包括譬如负责记录网站来访人数的部件 记录软件系统内部事件 出错信息的部件 或是对系统的表现进行检查的部件等 这些部件都必须集中管理 不可政出多头
这些资源管理器构件必须只有一个实例 这是其一 它们必须自行初始化 这是其二 允许整个系统访问自己这是其三 因此 它们都满足单例模式的条件 是单例模式的应用
一个例子 Windows 回收站
Windows x 以后的视窗系统中都有一个回收站 下图就显示了Windows 的回收站
在整个视窗系统中 回收站只能有一个实例 整个系统都使用这个惟一的实例 而且回收站自行提供自己的实例 因此 回收站是单例模式的应用
双重检查成例
在本章最后的附录里研究了双重检查成例 双重检查成例与单例模式并无直接的关系 但是由于很多C 语言设计师在单例模式里面使用双重检查成例 所以这一做法也被很多Java 设计师所模仿 因此 本书在附录里提醒读者 双重检查成例在Java 语言里并不能成立 详情请见本章的附录
单例模式的结构
单例模式有以下的特点
…… 单例类只可有一个实例
…… 单例类必须自己创建自己这惟一的实例
…… 单例类必须给所有其他对象提供这一实例
虽然单例模式中的单例类被限定只能有一个实例 但是单例模式和单例类可以很容易被推广到任意且有限多个实例的情况 这时候称它为多例模式(Multiton Pattern) 和多例类(Multiton Class) 请见 专题 多例(Multiton )模式与多语言支持 一章 单例类的简略类图如下所示
由于Java 语言的特点 使得单例模式在Java 语言的实现上有自己的特点 这些特点主要表现在单例类如何将自己实例化上
饿汉式单例类饿汉式单例类是在Java 语言里实现得最为简便的单例类 下面所示的类图描述了一个饿汉式单例类的典型实现
从图中可以看出 此类已经自已将自己实例化
代码清单 饿汉式单例类
public class EagerSingleton { private static final EagerSingleton m_instance = new EagerSingleton() /** * 私有的默认构造子*/ private EagerSingleton() { } /** * 静态工厂方法*/ public static EagerSingleton getInstance()
{
Java 与模式return m_instance }
读者可以看出 在这个类被加载时 静态变量m_instance 会被初始化 此时类的私有构造子会被调用 这时候 单例类的惟一实例就被创建出来了
Java 语言中单例类的一个最重要的特点是类的构造子是私有的 从而避免外界利用构造子直接创建出任意多的实例 值得指出的是 由于构造子是私有的 因此 此类不能被继承
懒汉式单例类
与饿汉式单例类相同之处是 类的构造子是私有的 与饿汉式单例类不同的是 懒汉式单例类在第一次被引用时将自己实例化 如果加载器是静态的 那么在懒汉式单例类被加载时不会将自己实例化 如下图所示 类图中给出了一个典型的饿汉式单例类实现
代码清单 懒汉式单例类
package javapatterns singleton demos public class LazySingleton { private static LazySingleton m_instance = null /** * 私有的默认构造子 保证外界无法直接实例化*/ private LazySingleton() { } /** * 静态工厂方法 返还此类的惟一实例*/ synchronized public static LazySingleton getInstance()
{ if (m_instance == null)
{ m_instance = new LazySingleton() } return m_instance }
读者可能会注意到 在上面给出懒汉式单例类实现里对静态工厂方法使用了同步化 以处理多线程环境 有些设计师在这里建议使用所谓的 双重检查成例 必须指出的是 双重检查成例 不可以在Java 语言中使用 不十分熟悉的读者 可以看看后面给出的小节
同样 由于构造子是私有的 因此 此类不能被继承 饿汉式单例类在自己被加载时就将自己实例化 即便加载器是静态的 在饿汉式单例类被加载时仍会将自己实例化 单从资源利用效率角度来讲 这个比懒汉式单例类稍差些
从速度和反应时间角度来讲 则比懒汉式单例类稍好些 然而 懒汉式单例类在实例化时 必须处理好在多个线程同时首次引用此类时的访问限制问题 特别是当单例类作为资源控制器 在实例化时必然涉及资源初始化 而资源初始化很有可能耗费时间 这意味着出现多线程同时首次引用此类的机率变得较大
饿汉式单例类可以在Java 语言内实现 但不易在C++ 内实现 因为静态初始化在C++ 里没有固定的顺序 因而静态的m_instance 变量的初始化与类的加载顺序没有保证 可能会出问题 这就是为什么GoF 在提出单例类的概念时 举的例子是懒汉式的 他们的书影响之大 以致Java 语言中单例类的例子也大多是懒汉式的 实际上 本书认为饿汉式单例类更符合Java 语言本身的特点
登记式单例类
登记式单例类是GoF 为了克服饿汉式单例类及懒汉式单例类均不可继承的缺点而设计的 本书把他们的例子翻译为Java 语言 并将它自己实例化的方式从懒汉式改为饿汉式 只是它的子类实例化的方式只能是懒汉式的 这是无法改变的 如下图所示是登记式单例类的一个例子 图中的关系线表明 此类已将自己实例化
代码清单 登记式单例类
import java util HashMap public class RegSingleton { static private HashMap m_registry = new HashMap() static { RegSingleton x = new RegSingleton() m_registry put( x getClass() getName() x) } /** * 保护的默认构造子*/ protected RegSingleton() {} /** * 静态工厂方法 返还此类惟一的实例*/ static public RegSingleton getInstance(String name)
{ if (name == null)
{ name = javapatterns singleton demos RegSingleton } if (m_registry get(name) == null)
{ try { m_registry put( name Class forName(name) newInstance() ) } catch(Exception e)
{ System out println( Error happened ) } return (RegSingleton) (m_registry get(name) ) } /** * 一个示意性的商业方法*/ public String about()
{ return Hello I am RegSingleton }它的子类RegSingletonChild 需要父类的帮助才能实例化 下图所示是登记式单例类子类的一个例子 图中的关系表明 此类是由父类将子类实例化的
下面是子类的源代码
代码清单 登记式单例类的子类
import java util HashMap public class RegSingletonChild extends RegSingleton { public RegSingletonChild() {} /** * 静态工厂方法*/ static public RegSingletonChild getInstance()
{ return (RegSingletonChild)
RegSingleton getInstance( javapatterns singleton demos RegSingletonChild ) } /** * 一个示意性的商业方法*/ public String about()
{ return Hello I am RegSingletonChild }
在GoF 原始的例子中 并没有getInstance() 方法 这样得到子类必须调用的getInstance(String name)方法并传入子类的名字 因此很不方便 本章在登记式单例类子类的例子里 加入了getInstance() 方法 这样做的好处是RegSingletonChild 可以通过这个方法 返还自已的实例 而这样做的缺点是 由于数据类型不同 无法在RegSingleton 提供这样一个方法 由于子类必须允许父类以构造子调用产生实例 因此 它的构造子必须是公开的 这样一来 就等于允许了以这样方式产生实例而不在父类的登记中 这是登记式单例类的一个缺点
lishixinzhi/Article/program/Java/gj/201311/27416