单例设计模式
什么是设计模式
- 静态方法和属性的经典实用
- 设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式。设计模式就像是经典的棋谱,不同的棋局,我们用不同的棋谱,免去我们自己再思考和摸索
什么是单例模式
-
单例:就是单个的实例
-
所谓的类的单例设计模式,就是采用一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法
-
单例模式有两种方式:
-
饿汉式(只有类被加载了,该对象就会被创建)
- 将构造器私有化
- 在类的内部之间创建(该对象是static)
- 提供一个公共的static方法,返回对象
例如,我们规定一个人必须专一,只能有一个女朋友!
package com.singleton; public class SingleTon { public static void main(String[] args) { GirlFriend instance = GirlFriend.getInstance(); System.out.println(instance); //无论你怎么创建,该对象都是同一个 GirlFriend instance1 = GirlFriend.getInstance(); System.out.println(instance1); //返回结果为True System.out.println(instance==instance1); } } class GirlFriend{ private String name ; //在类内部创建了对象,加static是为了可以在静态方法中返回girlFriend对象 private static GirlFriend girlFriend = new GirlFriend("小红"); //构造器私有化 private GirlFriend(String name){ this.name = name; } public static GirlFriend getInstance(){ return girlFriend; } @Override public String toString() { return "GirlFriend{" + "name='" + name + '\'' + '}'; } }
由于类被加载之后,对象无论如何都会被创建,会造成资源的浪费。
package com.singleton; public class SingleTon { public static void main(String[] args) { System.out.println(GirlFriend.n); } } class GirlFriend{ private String name ; public static int n = 100; //对象,通常是重量级的对象,饿汉模式可能造成创建了对象,但没有使用 private static GirlFriend girlFriend = new GirlFriend("小红"); //构造器私有化 private GirlFriend(String name){ System.out.println("构造器被调用了"); this.name = name; } public static GirlFriend getInstance(){ return girlFriend; } @Override public String toString() { return "GirlFriend{" + "name='" + name + '\'' + '}'; } }
使用懒汉式可以很好的解决这个问题
-
懒汉式(不调用就不会创建对象)
- 将构造器私有化
- 定义一个static静态属性对象
- 提供一个public的static方法,可以返回一个对象
懒汉式:只有当用户使用getInstance时才会返回一个对象。后面再调用时,会返回上次创建的对象
package com.singleton; public class SingleTon01 { public static void main(String[] args) { System.out.println(Cat.n); System.out.println("================"); Cat cat = Cat.getInstance(); System.out.println(cat); } } class Cat{ private String name; public static int n = 100; private static Cat cat; private Cat(String name){ System.out.println("构造器被调用"); this.name = name; } public static Cat getInstance(){ //判断有没有创建Cat对象 if(cat == null){ cat = new Cat("miao"); } return cat; } @Override public String toString() { return "Cat{" + "name='" + name + '\'' + '}'; } }
-
-
饿汉式VS懒汉式
- 二者最主要的区别在于创建对象的时机不同:饿汉式是在类加载就创建了对象实例而懒汉式是在使用时才创建
- 饿汉式不存在线程安全问题,懒汉式存在线程安全问题
- 饿汉式存在浪费资源的可能。因为如果程序员一个对象实例都没有使用,那么饿汉式创建的对象就浪费了,懒汉式是使用时才创建,就不存在这个问题。
- 在我们的JavaSE标准类中,java.lang.Runtime就是经典的单例模式