设计模式一--单例设计模式
一、定义
Singleton Pattern:
确保一个类只有一个实例,并且自行实例化并向整个系统提供这个实例。
二、分类
饿汉式单例类:类加载时就进行对象的实例化
懒汉式单例类:第一次引用类时,才进行对象的实例化。
三、核心代码
3.1 饿汉式
class Singleton{ private static Singleton m_instance=new Singleton(); //构造方法私有,保证外界无法直接实例化 private Singleton(){ } //通过该方法获得实例对象 public static Singleton getInstances(){ return m_instance; }}
3.2 懒汉式
class Singleton2{ private static Singleton2 _instance=null; //构造方法私有,保证外界无法直接实例化 private Singleton2(){ } //通过该方法获得实例对象 public static Singleton2 getInstances(){ if(_instance==null){ _instance=new Singleton2(); } return _instance; }}
四、实例
4.1 饿汉式
class Singleton{ //成员变量x用来测试 int x; private static Singleton m_instance=new Singleton(); //构造方法私有,保证外界无法直接实例化 private Singleton(){ } //通过该方法获得实例对象 public static Singleton getInstances(){ return m_instance; }} public class SingletonPattern { public static void main(String[] args) { Singleton.getInstances(); Singleton.getInstances().x=1; }}
4.2 懒汉式
class Singleton2{ //成员变量x用来测试 int x; private static Singleton2 _instance=null; //构造方法私有,保证外界无法直接实例化 private Singleton2(){ } //通过该方法获得实例对象 public static Singleton2 getInstances(){ if(_instance==null){ _instance=new Singleton2(); } return _instance; }} public class SingletonPattern2 { public static void main(String[] args) { Singleton2.getInstances(); Singleton2.getInstances().x=1; System.out.println(Singleton2.getInstances().x=1); }}
五、单例模式的优缺点
5.1 优点
只有一个实例,减少内存开销,避免对资源的多重占用
可以设置全局访问点,优化和共享资源访问
5.2 缺点
无法创建子类
单例模式与单一职责原则有冲突
六、单例模式的使用场景
要求生成唯一序列号的地方
在整个项目中需要一个共享访问点和共享数据
创建一个对象消耗的资源太多
需要定义大量的静态常量和静态方法(如工具类)的环境
七、单例模式的应用实例
7.1 代码
1 class GlobalNum{ 2 3 private int num=0; 4 5 private static GlobalNum globalNum=new GlobalNum(); 6 7 // 8 9 public static GlobalNum getInstance() {10 11 return globalNum;12 13 }14 15 //synchronized同步化16 17 public synchronized int getNum() {18 19 return num++;20 21 }22 23 public synchronized void setNum(int num) {24 25 this.num = num;26 27 }28 29 }30 31 32 33 class NumbelThread extends Thread{34 35 private String threadName;36 37 public NumbelThread(String name) {38 39 threadName=name;40 41 }42 43 44 45 public void run(){46 47 GlobalNum globalNum=GlobalNum.getInstance();48 49 //循环访问,输出访问次数50 51 for (int i = 0; i < 5; i++) {52 53 System.out.println(threadName+"第"+globalNum.getNum()+"次访问");54 55 56 57 }58 59 }60 61 }62 63 64 65 public class SingletonDemo {66 67 68 69 public static void main(String[] args) {70 71 NumbelThread threadA=new NumbelThread("线程A");72 73 NumbelThread threadB=new NumbelThread("线程B");74 75 threadA.start();76 77 threadB.start();78 79 }80 81 82 83 }
7.2 运行结果
线程A第0次访问
线程B第1次访问
线程A第2次访问
线程A第4次访问
线程B第3次访问
线程B第6次访问
线程B第7次访问
线程A第5次访问
线程B第8次访问
线程A第9次访问