单例设计:
所谓的单例设计就是一个类只允许产生一个实例化对象。下面首先看一个简单的程序:
范例:编写一个简单的程序
class singleton{ public void print(){ System. out. print ("Hello, world!"); } } class singletonTest{ public static void main(String[] args){ Singleton s=null; //声明对象 s=new Singleton(); //实例化对象 s.print() } } |
以上程序在进行对象实例化的时候调用了Singleton类的无参构造方法,因为在Singleton类立并没有提供任何的构造方法,所以自动生成的一个无参的,什么都不做的构造方法。但是如果将该无参构造明确定义为一个私有的构造方法呢!
class Singleton { private Singleton(){} //所有的方法都是可以使用四种权限 public void print(){ System. out. print ("Hello, world!"); } } |
这个时候类中已经明确有了一私有无参构造方法,那么一定不会再自动生成一个默认无参构造方法,也就是说此时进行实例化一定会有错误。
错误:class singletonTest{ public static void main(String[] args){ Singleton s=null; //声明对象 s=new Singleton(); //实例化对象错误 s.print() } } |
首先一旦构造方法被私有化,那么就表示外部无法调用构造方法,也就意味着外部不能产生实例化对象。那么也就证明,此时的类是一个相对封闭的状态了。
1. 可是现在如果还行继续调用Singleton类中print()这个普通方法,那么就必须提供实例化对象,于是根据封装的特性,可以在类的内部产生一个实例化对象。
class Singleton { //在类的内部是允许访问私有结构的,所以可以在类的内部实例化对象 Singleton instance = new Singleton();//内部产生实例化对象 private Singleton(){} //所有的方法都是可以使用四种权限 public void print(){ System. out. print ("Hello, world!"); } } |
2. 现在Singleton类内部的instance对象(属性)是个普通属性,所有的普通属性必须在有实例化对象的时候才能够进行内存空间的分配,而现在外部无法产生实例化对象,所以就必须想一个办法,可以在Singleton类没有实例化对象产生时也可以将instance进行使用。那么自然会联系到要使用static关键字。
class Singleton { //在类的内部是允许访问私有结构的,所以可以在类的内部实例化对象 static Singleton instance = new Singleton();//内部产生实例化对象 private Singleton(){} //所有的方法都是可以使用四种权限 public void print(){ System. out. print ("Hello, world!"); } } public TestSingleton{ public static void main(String[] args){ Singleton s = null; //声明对象 s = Singleton.instance; //实例化对象 } } |
class Singleton { //在类的内部是允许访问私有结构的,所以可以在类的内部实例化对象 private static Singleton instance = new Singleton();//内部产生实例化对象 public static Singleton getInstance(){ return instance; } private Singleton(){} //所有的方法都是可以使用四种权限 public void print(){ System. out. print ("Hello, world!"); } } public class TestSingleton{ public static void main(String[] args){ Singleton s = null; //声明对象 s = Singleton.getInstance(); //实例化对象 } } |
首先现在的问题已经正常解决了,但是这样的做法的目的是什么呢?只希望类中产生唯一的一个实例化对象。
不过对于这种单例设计也有两种形式:懒汉式、饿汉式。之前的程序实际属于饿汉式的应用,因为不管你是否去使用Singleton类的对象,只要该类加载了,那么一定会自动创建好一个公共的instance对象。既然是饿汉式,就希望整体的操作之中只能够有一个实例化对象,所以一般还会为其追加上final。
范例:饿汉式单例设计
class Singleton { //在类的内部是允许访问私有结构的,所以可以在类的内部实例化对象 private final static Singleton INSTANCE = new Singleton();//内部产生实例化对象 public static Singleton getInstance(){ return INSTANCE; } private Singleton(){} //所有的方法都是可以使用四种权限 public void print(){ System. out. print ("Hello, world!"); } } public class TestSingleton{ public static void main(String[] args){ Singleton s = null; //声明对象 s = Singleton.getInstance(); //实例化对象 } } |
面试题:请编写一个Singleton程序,并说明程序的主要特点?
|
范例:懒汉式单例
- 指的是当第一次去使用Singleton类的时候才会为其进行实例化处理操作。
class Singleton { //在类的内部是允许访问私有结构的,所以可以在类的内部实例化对象 private static Singleton instance;//内部产生实例化对象 public static Singleton getInstance(){ if(instance = null){ //表示此时还没有实例化 instance= new Singleton(); } return instance; } private Singleton(){} //所有的方法都是可以使用四种权限 public void print(){ System. out. print ("Hello, world!"); } } public class TestSingleton{ public static void main(String[] args){ Singleton s = null; //声明对象 s = Singleton.getInstance(); //实例化对象 } } |
对于懒汉式和饿汉式理解就可以了,更多情况是需要你自己将单例设计的核心组成记住以及慢慢理解它的用法。
多例设计:(理解)
多例的对象的类实际上在生活中也经常出现,例如:要求描述一周时间数的类,只能有七个对象,描述性别的类的对象只能有两个,这都属于多例设计模式。
所谓的多例只是比单例追加多个内部实例化对象的产生而已。
范例:现在定义一个表示性别的多例类
class Sex { public static final int MALE_CMD = 1; public static final int FEMALE_CMD = 2; private static final Sex MALE = new Sex("男"); private static final Sex FEMALE = new Sex("女"); private String title; private Sex(String title){ //构造方法必须私有化 this.title = title; } public static Sex getInstance(int ch){ switch(ch){ case MALE_CMD: return MALE; case FEMALE_CMD: return FEMALE; default: return null; } } public String toString (){ return this.title; } } public class Test { public static void main(String[] args){ Sex a = Sex.getInstance(Sex.MALE_CMD) System. out. print(a); } } |
不管多例还是单例特点很明显:
- 构造方法私有化
- 类内部一定会提供一个static方法用于取得类的实例化对象
总结:
单例和多例的代码编写几率并不会很高,但是对于编码结构必须清楚,尤其是单例设计,很多面试会问。多例模式先理解概念,该概念已经被枚举取代了。 |