设计模式(一)—单例模式
最后更新于:2022-04-01 16:25:53
## 单例模式
英文名称:(Singleton Pattern)
**定义**:确保某一个类只用一个实例,而且自行实例化并向整个系统提供这个实例
UML图:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_57553407ce5ab.jpg)
~~~
public class SingletonTest {
public static void main(String[] args) {
//通过Singleton对外暴漏的方法,进行实例化。并保证只有一个实例
Singleton single = Singleton.getInstance();
System.out.println(single.toString());
}
}
//又称饿汉式单例模式
class Singleton{
private static final Singleton single = new Singleton();
private Singleton(){
}
public static Singleton getInstance(){
return single;
}
}
//又称懒汉式单例模式
//<span style="font-size:18px;">懒汉式单例模式在遇到高并发情况,系统有压力增大,可能会出现多个实例的对象。</span>
class Singleton1{
private static Singleton1 single = null;
private Singleton1(){
}
public static Singleton1 getInstance(){
if(single==null){
synchronized (Singleton1.class) { //
if(single==null){
single = new Singleton1();
}
}
}
return single;
}
}
~~~
**(按照书本上的总结,自己理解并不太深刻。。)**
**单例模式的优点:**
1、单例模式内存中只有一个实例,减少内存开支,一个对象需要频繁的创建和销毁。使用单例模式具有很大的优势。
2、单例只生成一个实例,减少系统的性能开销。
3、单例模式可以在避免对资源的多重占用。
4、单例模式可以在系统设置全局的访问点,优化和共享资源访问。
**单例模式的缺点:**
1、单例模式一般没有接口,扩展很困难。
2、单例对测试不利
3、单例与单一职责原则有冲突。
**单例的使用场景:**
1、要求生成唯一序列号的环境
2、在整个项目中需要一个共享访问点或访问数据
3、创建一个对象需要消耗的资源过多
4、需要定义大量的静态常量和静态方法。
**单例的拓展**
通过单例的拓展,让类只产生两个或者多个实例对象。
UML图
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_57553407e4478.jpg)
~~~
public class EmperorTest {
public static void main(String[] args) {
for(int i=0;i<5;i++){
//获取Emperor对象的实例
Emperor e = Emperor.getEmperor();
e.say();
}
}
}
class Emperor{
//定义一个list集合,用来存放对象的实例
private static List<Emperor> listEmperor = new ArrayList<Emperor>();
private static int maxNum = 2;
//定义一个list集合,为创建的对象设置编号。
private static List<String> listNumofEmperor = new ArrayList<String>();
//表示当前编号
private static int currentNum = 0;
//创建出所有的对象
static{
for(int i=0;i<maxNum;i++)
listEmperor.add(new Emperor("实例化.."+(i+1)+"..对象"));
}
private Emperor(String name){
listNumofEmperor.add(name);
}
public static Emperor getEmperor(){
Random random = new Random();
currentNum = random.nextInt(maxNum);
return listEmperor.get(currentNum);
}
public void say(){
System.out.println(listNumofEmperor.get(currentNum));
}
}
~~~