设计模式 (六)单例模式(Singleton)

单例模式就是确保一个类只有一个实例,并且该实例必须自动创建,并向整个系统提供该实例。这样保证了对外的对象的属性等均为一个实例,就像是银行取款

单例模式原理图:


单例模式分为饿汉式单例模式和懒汉式单例模式。

饿汉式单例模式代码

package com.designpattern.singleton;

public class HungrySingleton {
	private HungrySingleton() {
	}

	private static HungrySingleton instance = new HungrySingleton();

	public static HungrySingleton getInstance() {
		return instance;
	}
}

懒汉式单例模式代码

package com.designpattern.singleton;

public class LazySingleton {
	private LazySingleton() {

	}

	private static LazySingleton instance = null;

	public static synchronized LazySingleton getInstance() {
		if (instance == null) {
			instance = new LazySingleton();
		}
		return instance;
	}
}
事例中对于饿汉式是不管外部有没有调用都new出了一个对象,二懒汉式只有在外部调用的时候,并且是第一次的时候才new出来对象的,但是一定要放在sychronized下面

这样感觉像是懒汉模式是在调用的时候分配空间初始化instance的,但是自己感觉上面两种是一样的效果

在实例化先后顺寻的角度分析:饿汉式类内static 对象会在构造器调用前初始化,也就是最先初始化,但是只初始化一次就不再初始化了,毕竟是static的,在构造器之前也就是只有在使用这个类的时候,才实例化。同时后者懒汉式中私有的static也会在构造器之前初始化,但是是null,这样就在第一次调用这个类的时候对instance进行了初始化,但是之后就不会再初始化了,原因也是static,这样看起来对于懒汉和饿汉的初始化和构造过程是一样的。

不过说道具体的地方饿汉式是在加载类的时候创建对象,而懒汉式是在调用getInstance时候创建对象,那么这样他们在创建的时候还是用一定的区别的。

下面借着这个Singleton模式简单的做了一个Log工具,实现对于一个日志工具不会多次初始化,并且不会覆盖掉而是尾加,Log4j就是一个Singleton的实例

package com.designpattern.singleton;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Log {

	private static final String DefalutLogFilePathName = System
			.getProperty("user.dir")
			+ File.separator + "user.log";
	private static Log log;
	private static PrintWriter pw;

	private Log() {
		pwinit();
	}

	public static synchronized void log(String message) {
		if (log == null || pw == null) {
			log = new Log();
		}
		if (pw != null) {
			pw.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
					.format(new Date())
					+ " : " + message);
		}
	}

	public static void destroy() {
		log = null;
		if (pw != null) {
			pw.close();
		}
	}

	private void pwinit() {
		if (pw == null) {
			try {
				pw = new PrintWriter(new FileWriter(DefalutLogFilePathName,
						true), true);
			} catch (IOException e) {
				e.printStackTrace();
				pw = null;
			}
		}
	}
}

在Client端对Log进行操作,不会覆盖结果,测试成功

package com.designpattern.singleton;

public class Client {
	public static void main(String[] args) {

		System.out.print("Log");
		System.out.print("\t");
		Log.log("start");
		Log.log("middle");
		Log.log("end");
		Log.destroy();

	}
}
输出结果:

2012-04-05 14:46:15 : start
2012-04-05 14:46:15 : middle
2012-04-05 14:46:15 : end
在单例模式中,客户调用类的实例时,只能调用一个公共接口,这就是为整个开发团队提供了共享的概念。

但是但是模式的类在实例化以后,不能被别的类继承,在分布式系统中,当系统中的单例类被复制运行在多个虚拟机下时,在每一个虚拟机下都会创建一个实例对象,此时如果想知道具体那个虚拟机下运行着哪个单例对象是很困难的,而且单例类很难实现序列化。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值