对于所有的Java开发者而言,项目中最为常见的三个设计模式:工厂设计模式、代理设计模式、单例设计模式。
一、简介(单例设计模式)
如果一个类中定义有普通方法,那么这些普通方法一定要通过本类的实例化对象才可以进行调用。
**例:**传统调用
class Singleton{
public void printI(){
System.out.print1n("传统调用");
}
public class TestDemo{//主类
public static void main(String args[]){//主方法
Singleton instance=new Singleton();
instance.prin();
}
程序执行结果:
传统调用
在本程序之中的“Singleton”类里面是一个普通的类,并且由于该类中并没有进行任何构造方法的定义,所以这个类中会自动生成一个无参的什么都不做的构造方法,正是因为如此,所以可以在外部进行无参构造的调用。
例:现在想对Singleton类做一个修改
class Singleton{
private Singleton(){ } //无参私有构造方法
public void print(){
System.out.println("单例");
}
}
public class TestSingleton {
public static void main(String[] args) {
Singleton s = null;
s = new Singleton();
}
}
如果构造方法被私有化了,那么类的外部将无法进行该构造方法的调用,那么也就意味着这个类无法进行新的实例化对象的生成,于是此时就需要思考,如何可以在Singleton类中通过一些新结构的设计,让外部可以获取本类实例。
1、使用private进行私有化的结构只允许在本类之中进行访问,所以此时Singleton类中的无参构造方法其实只有Singleton类自己可以调用,那么就必须找到一种结构即可以在内部调用Singleton类构造,又可以不受到Singleton类实例化对象的限制,那么自然可以想到的是static方法。
class Singleton{
private Singleton(){ } //无参私有构造方法
public void print(){
System.out.println("单例");
}
public static Singleton getInstance(){
return new Singleton();
}
}
public class TestSingleton {
public static void main(String[] args) {
Singleton s = null;
s = Singleton.getInstance();
s.print();
}
}
程序执行结果:
单例
以上的操作的确实现了外部获取Singleton类实例化对象的需求,但是这种实现就像在脱裤子放屁,多此一举,因为如果此时不在构造方法中追加private,也可以实现同样的功能。
二、饿汉式单例
2、构造方法的主要功能是获取一个类中的实例化对象,每调用一次构造方法就都可以获取一个新的实例化对象;如果说现在要想限制一个类中的实例化对象个数的产生,那么此时最好的控制就是将构造方法隐藏,那么此时就需要进行程序结构的修改,让整个类中只维持一个实例化对象;
3、类中的构造方法被私有化之后,就只能够在类中进行对象的实例化操作;
class Singleton{
private static final Singleton INSTANCE = new Singleton();
private Singleton(){ } //无参私有构造方法
public static Singleton getInstance(){
return INSTANCE;
}
public void print(){
System.out.println("实现了最核心的单例设计模式(饿汉式)");
}
}
public class TestSingleton {
public static void main(String[] args) {
Singleton s = null;
s = Singleton.getInstance();
s.print();
}
}
程序执行结果:
实现了最核心的单例设计模式(饿汉式)
以上就实现了一个最为核心的单例设计模式,不管外部调用多少次的getlnstance()方法,那么在整个的系统内部只维持了唯一的一个Singleton类的实例。
对于单例设计模式实际上会分为两种:饿汉式单例、懒汉式单例。在之前所讲解的就属于饿汉式单例,之所以将其称为饿汉式主要的原因在于,Singleton里面会始终维持一个INSTANCE的实例化对象,然而并不关心这个对象是否被使用。
三、懒汉式单例
而懒汉式单例设计的最大特点在于:第一次使用的时候才会进行实例化,
不使用不进行实例化。
(注意:如果面试的时候让你写单例设计模式,要写懒汉式单例设计模式)
例:懒汉式单例设计模式
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("实现了最核心的单例设计模式(懒汉式)");
}
}
public class TestSingleton {
public static void main(String[] args) {
Singleton s = null;
s = Singleton.getInstance();
s.print();
}
}
实现了最核心的单例设计模式(懒汉式)
饿汉式的单例实现要比懒汉式的单例实现更加简单一些。
后面会对懒汉单例设计模式做更加详细的说明。
三、多例设计模式
与单例设计模式对应的还有一种称为多例设计模式,多例设计模式的主要特点是可以在一个类中定义指定的几个实例化对象。
例如:在进行一周时间数描述的时候,对象应该只有7个,在进行颜色基色描述的时候应该只有三个实例化对象,与单例最大的区别在于,此时要维护的是多个对象,所以对于实例化对象的获取也需要有所区分。
不管是单例设计模式还是多例设计模式,一定要记住需要将构造方法私有化,只有私有化的操作才可以实现实例化对象的控制。
例:描述一个多例设计,通过颜色基色描述
class Color {
private String info;
private static final Color RED = new Color("红色");
private static final Color GREEN = new Color("绿色");
private static final Color BLUE = new Color("蓝色");
private Color(String info) {
this.info = info;
}
public static Color getInstance(String color) {
switch (color) {
case "red":
return RED;
case "green":
return GREEN;
case "blue":
return BLUE;
default:
return null;
}
}
@Override
public String toString() {
return this.info;
}
}
public class TestMultion {
public static void main(String[] args) {
Color red = Color.getInstance("red");
System.out.println(red);
}
}
程序执行结果:
红色
不管是单例设计模式还是多例设计模式,一定要记住需要将构造方法私有化,只有私有化的操作才可以实现实例化对象的控制。