JAVA设计模式---单例模式(singleton)
2016-08-25 10:59
253 查看
1.首先看一个Java的简单版本的log类
public class LogUtil {
private static LogUtil sLogUtil;
public final int DEGUB = 0;
public final int INFO = 1;
public final int ERROR = 2;
public final int NOTHING = 3;
public int level = DEGUB;
private LogUtil() {
}
public static LogUtil getInstance() {
if (sLogUtil == null) {
sLogUtil = new LogUtil();
}
return sLogUtil;
}
public void debug(String msg) {
if (DEGUB >= level) {
System.out.println(msg);
}
}
public void info(String msg) {
if (INFO >= level) {
System.out.println(msg);
}
}
public void error(String msg) {
if (ERROR >= level) {
System.out.println(msg);
}
}
}首先将LogUtil的构造函数私有化,这样就无法使用new关键字来创建LogUtil的实例了。然后使用一个sLogUtil私有静态变量来保存实例,并提供一个公有的getInstance方法用于获取LogUtil的实例,在这个方法里面判断如果sLogUtil为空,就new出一个新的LogUtil实例,否则就直接返回sLogUtil。这样就可以保证内存当中只会存在一个LogUtil的实例了。单例模式完工!这时打印日志的代码需要改成如下方式:
2.对于上面的代码在多线程的时候可能会出现问题。
public static LogUtil getInstance() {
if (sLogUtil == null) {
sLogUtil = new LogUtil();
}
return sLogUtil;
}
如果现在有两个线程同时在执行getInstance方法,第一个线程刚执行完第2行,还没执行第3行,这个时候第二个线程执行到了第2行,它会发现sLogUtil还是null,于是进入到了if判断里面。这样你的单例模式就失败了,因为创建了两个不同的实例。
方案一:public synchronized static LogUtil getInstance() {
if (sLogUtil == null) {
sLogUtil = new LogUtil();
}
return sLogUtil;
}方案二:
public static LogUtil getInstance() {
synchronized (LogUtil.class) {
if (sLogUtil == null) {
sLogUtil = new LogUtil();
}
return sLogUtil;
}
}方案三:
public static LogUtil getInstance() {
if (sLogUtil == null) {
synchronized (LogUtil.class) {
if (sLogUtil == null) {
sLogUtil = new LogUtil();
}
}
}
return sLogUtil;
}
方案一与方案二都解决了是否是单例(singleton)的问题,但是每次调用getInstance(),都会被同步锁同步,降低了效率。
方案三应该是最佳的方案。
3.下面是我自己写的一个android中用到的LOG类
package Util;
import android.util.Log;
/**
* Created by lq on 16-8-25.
*
*/
public class LogUtil {
private static LogUtil mLogUtil;
private final int DEBUG = 0;
private final int INFO = 1;
private final int ERROR = 2;
private final int NOTHING = 3;
private int mLevel = DEBUG;
private LogUtil(){
}
public LogUtil getInstance(){
if(mLogUtil == null){
synchronized (LogUtil.class){
if(mLogUtil == null) mLogUtil = new LogUtil();
}
}
return mLogUtil;
}
public void setLevel(int level){
if(level < 4 && level > -1)
mLevel = level;
}
public void d(String tag, String msg){
if(DEBUG >= mLevel){
Log.d(tag,msg);
}
}
public void i(String tag, String msg){
if(INFO >= mLevel){
Log.i(tag,msg);
}
}
public void e(String tag, String msg){
if(ERROR >= mLevel){
Log.e(tag,msg);
}
}
}
singleton优秀博客: http://blog.csdn.net/guolin_blog/article/details/8860649
public class LogUtil {
private static LogUtil sLogUtil;
public final int DEGUB = 0;
public final int INFO = 1;
public final int ERROR = 2;
public final int NOTHING = 3;
public int level = DEGUB;
private LogUtil() {
}
public static LogUtil getInstance() {
if (sLogUtil == null) {
sLogUtil = new LogUtil();
}
return sLogUtil;
}
public void debug(String msg) {
if (DEGUB >= level) {
System.out.println(msg);
}
}
public void info(String msg) {
if (INFO >= level) {
System.out.println(msg);
}
}
public void error(String msg) {
if (ERROR >= level) {
System.out.println(msg);
}
}
}首先将LogUtil的构造函数私有化,这样就无法使用new关键字来创建LogUtil的实例了。然后使用一个sLogUtil私有静态变量来保存实例,并提供一个公有的getInstance方法用于获取LogUtil的实例,在这个方法里面判断如果sLogUtil为空,就new出一个新的LogUtil实例,否则就直接返回sLogUtil。这样就可以保证内存当中只会存在一个LogUtil的实例了。单例模式完工!这时打印日志的代码需要改成如下方式:
LogUtil.getInstance().debug("Hello World");
2.对于上面的代码在多线程的时候可能会出现问题。
public static LogUtil getInstance() {
if (sLogUtil == null) {
sLogUtil = new LogUtil();
}
return sLogUtil;
}
如果现在有两个线程同时在执行getInstance方法,第一个线程刚执行完第2行,还没执行第3行,这个时候第二个线程执行到了第2行,它会发现sLogUtil还是null,于是进入到了if判断里面。这样你的单例模式就失败了,因为创建了两个不同的实例。
方案一:public synchronized static LogUtil getInstance() {
if (sLogUtil == null) {
sLogUtil = new LogUtil();
}
return sLogUtil;
}方案二:
public static LogUtil getInstance() {
synchronized (LogUtil.class) {
if (sLogUtil == null) {
sLogUtil = new LogUtil();
}
return sLogUtil;
}
}方案三:
public static LogUtil getInstance() {
if (sLogUtil == null) {
synchronized (LogUtil.class) {
if (sLogUtil == null) {
sLogUtil = new LogUtil();
}
}
}
return sLogUtil;
}
方案一与方案二都解决了是否是单例(singleton)的问题,但是每次调用getInstance(),都会被同步锁同步,降低了效率。
方案三应该是最佳的方案。
3.下面是我自己写的一个android中用到的LOG类
package Util;
import android.util.Log;
/**
* Created by lq on 16-8-25.
*
*/
public class LogUtil {
private static LogUtil mLogUtil;
private final int DEBUG = 0;
private final int INFO = 1;
private final int ERROR = 2;
private final int NOTHING = 3;
private int mLevel = DEBUG;
private LogUtil(){
}
public LogUtil getInstance(){
if(mLogUtil == null){
synchronized (LogUtil.class){
if(mLogUtil == null) mLogUtil = new LogUtil();
}
}
return mLogUtil;
}
public void setLevel(int level){
if(level < 4 && level > -1)
mLevel = level;
}
public void d(String tag, String msg){
if(DEBUG >= mLevel){
Log.d(tag,msg);
}
}
public void i(String tag, String msg){
if(INFO >= mLevel){
Log.i(tag,msg);
}
}
public void e(String tag, String msg){
if(ERROR >= mLevel){
Log.e(tag,msg);
}
}
}
singleton优秀博客: http://blog.csdn.net/guolin_blog/article/details/8860649
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager