- 单例设计模式的特点;
- 多例设计模式的特点。
单例设计模式
class Singleton{//编写一个普通类
public void print(){
System.out.println("www.mldn.cn");
}
}
这个时候程序类给出后肯定是直接实例化对象,而后调用方法。
public class Hello{
public static void main(String args[]){
Singleton inst = null;//声明对象
inst = new Singleton();//实例化对象
inst.print();
}
}
再次使得Singleton类中一定存在有无参构造方法,因为自动生成的。但是构造方法虽然一般都会使用public声明,可是也可以使用private声明。
class Singleton{//编写一个普通类
private Singleton(){}//构造方法四私有了
public void print(){
System.out.println("www.mldn.cn");
}
}
public class Hello{
public static void main(String args[]){
Singleton inst = null;//声明对象
inst = new Singleton();//实例化对象
inst.print();
}
}
因为此时构造方法被私有化了,所以无法从外部进行构造方法的调用。现在在构造方法和print()方法没有做任何修改的情况下,做一些适当的Singleton变化让类外部可以得到Singleton类的实例化对象,并且调用print()方法。于是有了以下分析:
分析一:现在程序的关键是在于构造方法上使用了private(private Singleton(){}),那么对于private的特点只能够在本类中进行访问。那么现在换一个思路:能不能说在本类中准备好一个实例化对象呢?
class Singleton{//编写一个普通类
Singleton instance = new Singleton();
private Singleton(){}//构造方法四私有了
public void print(){
System.out.println("www.mldn.cn");
}
}
分析二:此时内部声明的instance属性属于一个普通的属性,那么普通属性有一个前提:在实例化对象后才可以调用,但是现在外部类无法实例化对象,那么就考虑使用static,因为static不受到实例化控制。
class Singleton{//编写一个普通类
static Singleton instance = new Singleton();
private Singleton(){}//构造方法四私有了
public void print(){
System.out.println("www.mldn.cn");
}
}
public class Hello{
public static void main(String args[]){
Singleton inst = null;//声明对象
inst = Singleton.instance;//实例化对象
inst.print();
}
}
分析三:强调过只要是类中的属性都应该进行private封装,所以以上代码中的instance属性也应该进行封装,那么一旦封装了,就必须通过方法访问,那么此时要访问的是static属性,并且类无法直接在外部产生实例化对象,那么就编写一个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 Hello{
public static void main(String args[]){
Singleton inst = null;//声明对象
inst = Singleton.getInstance();//实例化对象
inst.print();
}
}
分析四:这么写代码折腾一圈最终目的还是在外部使用实例化对象调用方法,意义在哪里?
public class Hello{
public static void main(String args[]){
Singleton instA = null;//声明对象
Singleton instB = null;//声明对象
Singleton instC = null;//声明对象
instA = Singleton.getInstance();//实例化对象
instB = Singleton.getInstance();
instC = Singleton.getInstance();
instA.print();
}
}
通过内存关系可以发现,不管外部有多少个对象的声明,最终所产生的实例化对象只有一个。也就是说本程序限制了实例化对象的产生,只维持了一个。
之所以将构造方法私有就是切断了构造方法,那么自然无法产生新的实例化对象。
分析五:缺陷。为了保证整个代码在操作的过程中只会存在唯一的一个实例化对象,并且不可更改,则可以利用final声明。
面试题:请编写一个Singleton程序,并说明程序的主要特点
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 Hello{
public static void main(String args[]){
Singleton inst = null;//声明对象
inst = Singleton.getInstance();
inst.print();
}
}
构造方法私有化,外部无法产生新的实例化对象,只能够通过类提供的static方法取唯一的一个对象的引用。
对于单例设计模式有两类:饿汉式(以上代码)、懒汉式。
- 饿汉式:不管程序中是否有对象需要使用此类,此类的对象都要实例化好;
- 懒汉式:在第一次使用的时候才进行实例化。
范例:观察懒汉式
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 Hello{
public static void main(String args[]){
Singleton inst = null;//声明对象
inst = Singleton.getInstance();
inst.print();
}
}
这两个分类只是一个小小的概念,关键还是将之前的单例设计模式编写熟练。
多例设计模式
不管是单例设计还是多例设计,本质就一个:构造方法私有化,内部产生实例化对象,只不过单例设计只产生一个,多例设计会产生多个。
例如:现在要求描述一周时间数,只能够有七个对象;
例如:要求描述性别的类,只能有两个。
范例:性别的描述
class Sex{
public static final int MALE_CH = 1;
public static final int FEMALE_CH = 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_CH:
return MALE;
case FEMALE_CH:
return FEMALE;
default:
return null;
}
}
public String toString(){
return this.title;
}
}
public class Hello{
public static void main(String args[]){
Sex sex = Sex.getInstance(Sex.MALE_CH);
System.out.println(sex);
}
}
多例只是单例的衍生品,本质上没有区别。