单例模式和静态变量
看过很多对于单例模式的讨论,对于其中的一个问题,还是不太明白,希望牛人点明重点,醍醐灌顶。
比如说我要写一个类,来读取项目的配置文件。
可以有两种实现方法,
1,单例实现
import java.util.HashMap;
import java.util.Map;
/**
* 配置文件读取类的单例实现
*/
public class SinglePattern {
//静态私有对象
private static SinglePattern sp = new SinglePattern();
//配置文件的MAP
private Map configs;
/**
* 构造方法私有化
*/
private SinglePattern(){
//读取系统配置,放到配置文件的MAP里面去,这段代码省略...
configs = new HashMap();
}
/**
* 实例化方法
* @return 静态私有对象
*/
public static SinglePattern getInstance() {
return sp;
}
/**
* 读取配置文件
* @param key
* @return 配置信息
*/
public String getConfig(String key){
return configs.get(key);
}
}
2,静态实现
import java.util.HashMap;
import java.util.Map;
/**
* 配置文件读取类的静态实现
*/
public class StaticPattern {
//配置文件的MAP:设置成statci的变量,和单例一样,只有一份存在
private static Map configs;
/**
* 读取系统配置
*/
static{
//读取系统配置,放到配置文件的MAP里面去,这段代码省略...
configs = new HashMap();
}
/**
* 读取配置文件
* @param key
* @return 配置信息
*/
public static String getConfig(String key){
return configs.get(key);
}
}
这两种实现方法有什么不同吗,
很多项目采用的都是单例的实现,但是我感觉静态的实现更简单
望牛人点明
------解决方案--------------------
区别就是 第二种 可以改变 ,StaticPattern .configs =new HashMap();
在工程的任何一个地方 ,都可以改变configs 使他指向另一个内存地址。
第一种 SinglePattern 是不能被改变的 ,但是你在单例的类中定义了 全局的变量存在线程安全问题 ,内部的configs 也是可以改变的。
若果你的变量configs 用final 修饰 就不会被改变了 , 效果就一样了。
java中的静态变量只会被加载一次。
------解决方案--------------------
SinglePattern :内存中 存在一个 SinglePattern 这样类型的实例,(实例的存在也是因为用到所以new一个对象出来,用不到的话,这个 实例就不用new ,内存占用“可控”)
StaticPattern : 没有实例(也可以有,new出来一个),直接用类名点方法调用
理论上 类 SinglePattern 是有可能被 GC的,就是说这块内存是有可能被回收的
但是 StaticPattern 占用的内存 则会被一直占用。
个人理解
------解决方案--------------------
单例是为了提供全局唯一的访问点&&同步问题,你第二种写法会出现同步问题。
------解决方案--------------------
1.单状态枚举是最优单例实现
2.单例模式是反模式
3.单例靠不住,创建第二实例的方法太多。。
------解决方案--------------------
http://www.360doc.com/content/13/1028/16/11253639_324825197.shtml
楼主可以看看
------解决方案--------------------
1、首先纠正个楼上的错误,楼主你的第二种写法并没有把Map暴露出去,所以外部无法将configs指向别的对象,final不需要加。
2、回答楼主的问题,主要说为什么建议使用单例而不是类的静态方法,楼主注意下你第二种方式的configs是static的,且初始化也是在static方法块中的,如果初始化过程步骤很复杂,如果再用到很多的成员变量参与初始化都需要设计成static的,且静态初始化的控制权是在Java手上的,这么做可能导致混乱。
其实如果只是简单的映射配置文件,的确方法1、方法2都可行。
------解决方案--------------------
单例不在于怎么实现,在于怎么用。
大部分人都把单例用成了静态,那就跟静态区别不大。
设计模式本来就是给一些表面的东西起名字,没必要纠结这些概念。