课时109:单例设计
摘要:
1.单例设计具体内容
2.单例设计操作
3.单例的设计结构
4.单例设计特点
01.单例设计具体内容
单例设计模式(多例设计模式)主要是一种控制实例化对象产生个数的设计操作。
02.单例设计操作
2.1如果说现在有一个程序类,假设该程序类的定义如下:
class Singleton { public void print() { System. out. println("www.mldn.cn"); } } public class Java Demo {
这个代码写完之后, 外面能够产生无数个实例化对象。于是,每一个实例化对象都能够调用这个方法。
Public class Java Demo { public static void main(string args[]) { Singleton instance A = new Singleton() Singleton instance B = new Singleton() Singleton instance C = new Singleton() Instance A. print(); Instance B. print(); Instance C. print(); } }
执行代码后如图所示:
但是由于某些要求,现在要求 Singleton 这个类只允许提供有一个实例化对象。那么此时首先应该控制的就是构造方法。因为所有的新的实例化对象产生了,那么一定要调用构造方法,如果构造方法“没有了”,那么自然就无法产生实例化对象了。
范例:构造方法私有化了
所以按照上个示例来讲,这个构造方法不可能被删,那如果代码中这样写,如下所示:
class Singleton { private Singleton() { } //构造方法私有化了 public void print() { System. out. println("www.mldn.cn”); } } public class Java Demo { public static void main(string args []) { Singleton instance = null ; //声明对象 instance = null Singleton ();
现在已经将构造方法完全的私有化了,一旦私有化后,从正常道理上来讲,它已经无法执行了。现在再编译一下程序,会发现 “new“ 出错了。如下图:
现在声明化对象没有错误,而实例化对象有错误了。如下:
instance = new Singleton(); // 错误: Singleton()可以在Singleton 中访问 Private
但是现在是有一个严格要求的:必须产生有一个实例化对象,所以现在就必须想办法产生一个实例化对象交给交给客户端去调用。
2.2那么这个时候的分析如下:
(1)Private 访问权限的主要特点在于:不能在类外部访问,但是可以在类本身调用,所以现在可以考虑在类的内部调用构造;
在上述代码 class Singleton { 后添加:
private Singleton instance = new Singleton() ; private Singleton () {} // 构造方法私有化了 public void print() { System. out. println("www.mldn.cn"); } }
将这两段代码编译可发现能正常执行,如图:
(2)此时 Singleton 类内部的istance 属于一个普通的属性,而普通属性是在由实例化对象产生之后才会被调用的,那么这个时候外部无法产生实例化对象,所以这个属性就不能够访问到了,那么就必须考虑如何在没有实例化对象的时候获取此属性,那么只有 static 属性可以访问。
现在将 private Singleton instance = new Singleton() ;中的 private 换成 static,如下:
static Singleton instance = new Singleton() ;
这时的“new Singleton();“ 变成 ”Singleton . instance “
再在其后面加上输出:instance. print();
这时再将代码进行编译执行,如图:
(3)类中的属性应该封装后使用,所以理论上此时的 Instance 需要被封装起来,那么就需要通过一个 static 方法获得。如下:
class Singleton { private static Singleton instance = new Singleton() ; private Singleton() { } //构造方法私有化了 public static singleton getInstance() { return instance ; } public void print() { System. out. println("www.mldn .cn"); } } public class Java Demo { public static void main(string args[ ] ) { Singleton instance=null;//声明对象 instance: Singleton. getInstance() ; instance. print() ; } }
于是编译执行效果如图:
(4)整个代码从头强调的是只有一个实例化对象,这个时候虽然提供有static的实例化对象,但是这个对象依然可以被重新实例化。所以需要保证此时 Singleton 类内部的 Instance 无法再次实例化,那么应该使用 Final 定义。
class Singleton { private static final Singleton INSTANCE = new Singleton(); private singleton() { } // 构造方法私有化了 public static Singleton getInstance() { return INSTANCE; } public void print() { System. out. println("www.mldn .cn"); } } public class JavaDemo { public static void main(string args[ ] ) { Singleton instance=nul l; //声明对象 instance: Singleton. getInstance() ; instance. print() ; } }
再次编译执行,如图:
03.单例的设计结构
在很多情况下有些类是不需要重复产生对象的,例如:如果一个程序启动,那么现在肯定需要有一个类负责保存有一些程序加载的数据信息。
下图是一个单例的设计结构:
系统数据类的目的是在程序启动的时候进行一些重要数据的加载。不同的操作系统是有不同的数据,所以在这样的情况下这个数据系统类不是固定的,是动态加载的。
在 WINDOWS中也有单例设计的存在,比如 WINDOWS 里的回收站、每个磁盘上回收站,不管是磁盘还是桌面里的回收站,这个回收站都是共享的。这就是一个典型的单例设计模式。
对于单例设计模式也分为两种:懒汉式、饿汉式。在之前所定义的都属于饿汉式。在系统加载类的时候就会自动提供有 Singleton 类的实例化,而还有一种懒汉式,在第一次使用的时候进行实例化对象处理。
范例:将单例修改为懒汉式。
class Singleton { private static Singleton instance ; private Singleton() { } // 构造方法私有化了 public static Singleton getInstance() { if ( instance == null ) { //第一次使用 instance = new Singleton() ; //实例化对象 } return instance } public void print() { System . out . println("www.mldn.cn'); } } public class Java Demo { public static void main(string args[ ] ) { Singleton instance=null; //声明对象 instance: Singleton. getInstance() ; instance. print() ; } }
执行编译后如图所示:
后面在进行多线程的时候还会对懒汉式和饿汉式进行更加深入的分析。
04.单例设计特点
面试题:请编写一个 Singleton 程序,并说明其主要特点?
(1)代码如上,可以把懒汉式(后面需要考虑到线程同步问题)和饿汉式都写上;
(2)特点:构造方法私有化,类内部提供 Static 方法获取实例化对象,这样不管外部如何操作永远都只有一个实例化对象提供。
所以懒汉式和饿汉式是单例设计的最初形式,是最基本的概念。