JAVA的单例模式到底有几种变现形式?请列举?
JAVA单例模式的几种实现方法
1.饿汉式单例类
package pattern.singleton;
//饿汉式单例类.在类初始化时,已经自行实例化
public class Singleton1 {
//私有的默认构造子
private Singleton1() {}
//已经自行实例化
private static final Singleton1 single = new Singleton1();
//静态工厂方法
public static Singleton1 getInstance() {
return single;
}
}
2.懒汉式单例类
package pattern.singleton;
//懒汉式单例类.在第一次调用的时候实例化
public class Singleton2 {
//私有的默认构造子
private Singleton2() {}
//注意,这里没有final
private static Singleton2 single;
//只实例化一次
static{
single = new Singleton2();
}
//静态工厂方法
public synchronized static Singleton2 getInstance() {
if (single == null) {
single = new Singleton2();
}
return single;
}
}
在上面给出懒汉式单例类实现里对静态工厂方法使用了同步化,以处理多线程环境。有些设计师在这里建议使用所谓的”双重检查成例”.必须指出的是,”双重检查成例”不可以在Java 语言中使用。不十分熟悉的读者,可以看看后面给出的小节。 同样,由于构造子是私有的,因此,此类不能被继承。饿汉式单例类在自己被加载时就将自己实例化。即便加载器是静态的,在饿汉式单例类被加载时仍会将自己实例化。单从资源利用效率角度来讲,这个比懒汉式单例类稍差些。从速度和反应时间角度来讲,则比懒汉式单例类稍好些。然而,懒汉式单例类在实例化时,必须处
理好在多个线程同时首次引用此类时的访问限制问题,特别是当单例类作为资源控制器,在实例化时必然涉及资源初始化,而资源初始化很有可能耗费时间。这意味着出现多线程同时首次引用此类的机率变得较大。
饿汉式单例类可以在Java 语言内实现, 但不易在C++ 内实现,因为静态初始化在C++ 里没有固定的顺序,因而静态的m_instance 变量的初始化与类的加载顺序没有保证,可能会出问题。这就是为什么GoF 在提出单例类的概念时,举的例子是懒汉式的。他们的书影响之大,以致Java 语言中单例类的例子也大多是懒汉式的。实际上,本书认为饿汉式单例类更符合Java 语言本身的特点。
3.登记式单例类.
package pattern.singleton;
import java.util.HashMap;
import java.util.Map;
//登记式单例类.
//类似Spring里面的方法,将类名注册,下次从里面直接获取。
public class Singleton3 {
private static MapString,Singleton3 map = new HashMapString,Singleton3();
static{
Singleton3 single = new Singleton3();
map.put(single.getClass().getName(), single);
}
//保护的默认构造子
protected Singleton3(){}
//静态工厂方法,返还此类惟一的实例
public static Singleton3 getInstance(String name) {
if(name == null) {
name = Singleton3.class.getName();
System.out.println(“name == null”+”—name=”+name);
}
if(map.get(name) == null) {
try {
map.put(name, (Singleton3) Class.forName(name).newInstance());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return map.get(name);
}
//一个示意性的商业方法
public String about() {
return “Hello, I am RegSingleton.”;
}
public static void main(String[] args) {
Singleton3 single3 = Singleton3.getInstance(null);
System.out.println(single3.about());
}
}
java中哪些对象都是单例模式
下面列出一部分Java的单例类:
1)Runtime类
可以通过java.lang.Runtime#getRuntime()获取其实例
2)Desktop类
可以通过java.awt.Desktop#getDesktop()获取其实例
3)SecurityManager类,注意,虽然该类提供了公共无参构造函数,但其内部构造函数仍然以单例的模式在运行。可以说是单例的一种变形设计。
可以通过java.lang.System#getSecurityManager()获取其实例
Java中单例模式有哪些实现方法
单例模式大致有五种写法,分别为懒汉,恶汉,静态内部类,枚举和双重校验锁。 1、懒汉写法,常用写法 class LazySingleton{ private static LazySingleton singleton; private LazySingleton(){ } public static LazySingleton getInstance(){ i…
Java模式设计之单例模式(二)
在什么情况下使用单例模式
使用单例模式的条件
使用单例模式有一个很重要的必要条件
在一个系统要求一个类只有一个实例时才应当使用单例模式 反过来说 如果一个类可以有几个实例共存 那么就没有必要使用单例类 但是有经验的读者可能会看到很多不当地使用单例模式的例子 可见做到上面这一点并不容易 下面就是一些这样的情况
例子一
问 我的一个系统需要一些 全程 变量 学习了单例模式后 我发现可以使用一个单例类盛放所有的 全程 变量 请问这样做对吗?
答 这样做是违背单例模式的用意的 单例模式只应当在有真正的 单一实例 的需求时才可使用
一个设计得当的系统不应当有所谓的 全程 变量 这些变量应当放到它们所描述的实体所对应的类中去 将这些变量从它们所描述的实体类中抽出来 放到一个不相干的单例类中去 会使得这些变量产生错误的依赖关系和耦合关系
例子二
问 我的一个系统需要管理与数据库的连接 学习了单例模式后 我发现可以使用一个单例类包装一个Connection 对象 并在finalize()方法中关闭这个Connection 对象 这样的话 在这个单例类的实例没有被人引用时 这个finalize() 对象就会被调用 因此 Connection 对象就会被释放 这多妙啊
答 这样做是不恰当的 除非有单一实例的需求 不然不要使用单例模式 在这里Connection 对象可以同时有几个实例共存 不需要是单一实例
单例模式有很多的错误使用案例都与此例子相似 它们都是试图使用单例模式管理共享资源的生命周期 这是不恰当的
单例类的状态
有状态的单例类
一个单例类可以是有状态的(stateful) 一个有状态的单例对象一般也是可变(mutable) 单例对象
有状态的可变的单例对象常常当做状态库(repositary)使用 比如一个单例对象可以持有一个int 类型的属性 用来给一个系统提供一个数值惟一的序列号码 作为某个贩卖系统的账单号码 当然 一个单例类可以持有一个聚集 从而允许存储多个状态
没有状态的单例类
另一方面 单例类也可以是没有状态的(stateless) 仅用做提供工具性函数的对象 既然是为了提供工具性函数 也就没有必要创建多个实例 因此使用单例模式很合适 一个没有状态的单例类也就是不变(Immutable) 单例类 关于不变模式 读者可以参见本书的 不变(Immutable )模式 一章
多个JVM 系统的分散式系统
EJB 容器有能力将一个EJB 的实例跨过几个JVM 调用 由于单例对象不是EJB 因此 单例类局限于某一个JVM 中 换言之 如果EJB 在跨过JVM 后仍然需要引用同一个单例类的话 这个单例类就会在数个JVM 中被实例化 造成多个单例对象的实例出现 一个J EE应用系统可能分布在数个JVM 中 这时候不一定需要EJB 就能造成多个单例类的实例出现在不同JVM 中的情况
如果这个单例类是没有状态的 那么就没有问题 因为没有状态的对象是没有区别的 但是如果这个单例类是有状态的 那么问题就来了 举例来说 如果一个单例对象可以持有一个int 类型的属性 用来给一个系统提供一个数值惟一的序列号码 作为某个贩卖系统的账单号码的话 用户会看到同一个号码出现好几次
在任何使用了EJB RMI 和JINI 技术的分散式系统中 应当避免使用有状态的单例模式
多个类加载器
同一个JVM 中会有多个类加载器 当两个类加载器同时加载同一个类时 会出现两个实例 在很多J EE 服务器允许同一个服务器内有几个Servlet 引擎时 每一个引擎都有独立的类加载器 经有不同的类加载器加载的对象之间是绝缘的
lishixinzhi/Article/program/Java/gj/201311/27644
java开发在什么情况下使用单例模式?
使用原则如下:
1.单例模式:确保一个类只有一个实例,自行实例化并向系统提供这个实例
2.单例模式分类:饿单例模式(类加载时实例化一个对象给自己的引用),懒单例模式(调用取得实例的方法如getInstance时才会实例化对象)(java中饿单例模式性能优于懒单例模式,c++中一般使用懒单例模式)
单例模式(Singleton),也叫单子模式,是一种常用的软件设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。
比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息。这种方式简化了在复杂环境下的配置管理。
在java开发中,为什么要使用单例模式?
java单例模式确保一个类只有一个实例,自行提供这个实例并向整个系统提供这个实例。\x0d\x0a特点:\x0d\x0a1,一个类只能有一个实例;\x0d\x0a2,自己创建这个实例;\x0d\x0a3,整个系统都要使用这个实例。\x0d\x0a——————————–\x0d\x0aSingleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在。在很多操作中,比如建立目录 数据库连接都需要这样的单线程操作。一些资源管理器常常设计成单例模式。\x0d\x0a外部资源:譬如每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干个通信端口,系统应当集中管理这些通信端口,以避免一个通信端口被两个请求同时调用。\x0d\x0a内部资源,譬如,大多数的软件都有一个(甚至多个)属性文件存放系统配置。这样的系统应当由一个对象来管理这些属性文件。\x0d\x0a——————————–\x0d\x0a单例模式,能避免实例重复创建;\x0d\x0a单例模式,应用于避免存在多个实例引起程序逻辑错误的场合;\x0d\x0a单例模式,较节约内存。