23中设计模式值单例模式

我的理解:

单例就是有且只有一个对象,在一个类中只能生成一个对象。

这锅怎么理解的,举个栗子, 古代中皇帝就只有一个,每天臣子和百姓

就只认识这锅皇帝,这样有什么好处呢在我看来的话,这种情况下臣民们也好处理,大家叩拜、谈论的时候只要提及皇帝,每个人都知道指 的是谁,而不用在皇帝前面加上特定的称呼。

,要求一个类只能生成一个对象(皇帝),所有对象对它的依赖都是相同的,因为只 有一个对象,大家对它的脾气和习性都非常了解,建立健壮稳固的关系。

单例模式的定义

确保某一个类 只有一个实例,而且自行实例化并向整个系统提供这个实例。

(说人话就是,对象自己产生一个提供给别人用)

请添加图片描述
​Singleton类称为单例类,通过使用private的构造函数确保了在一个应用中只产生一个实
例,并且是自行实例化的(在Singleton中自己使用new Singleton())。
饿汉模式(饿汉模式下我就只能产生一个对象,你等不等待我就一个,供你使用的)

public class Singleton {
private static final Singleton singleton = new Singleton();
//限制产生多个对象
private Singleton(){
}
//通过该方法获得实例对象
public static Singleton getSingleton(){
return singleton;
}
//类中其他方法,尽量是static
public static void doSomething(){
}
}

上面的类我就产生了一个类只能只能产生一个实例对象,因为构造方法是private只能自己调用所以只能产生一个对象。
那就有人要问了,我们应该在什么地方使用单例模式的
● 由于单例模式在内存中只有一个实例,减少了内存开支,特别是一个对象需要频繁地
创建、销毁时,而且创建或销毁时性能又无法优化,单例模式的优势就非常明显。
● 单例模式可以在系统设置全局的访问点,优化和共享资源访问,例如可以设计一个单
例类,负责所有数据表的映射处理。
● 单例模式可以避免对资源的多重占用,例如一个写文件动作,由于只有一个实例存在
内存中,避免对同一个资源文件的同时写操作。
使用场景
● 要求生成唯一序列号的环境;
● 在整个项目中需要一个共享访问点或共享数据,例如一个Web页面上的计数器,可以
不用把每次刷新都记录到数据库中,使用单例模式保持计数器的值,并确保是线程安全的;
● 创建一个对象需要消耗的资源过多,如要访问IO和数据库等资源;

● 需要定义大量的静态常量和静态方法(如工具类)的环境,可以采用单例模式(当
然,也可以直接声明为static的方式)。
7.3.4 单例模式的注意事项
首先,在高并发情况下,请注意单例模式的线程同步问题。如果这种情况下的话会出现下面情况
?如一个线程A执行
到singleton = new Singleton(),但还没有获得对象(对象初始化是需要时间的),第二个线程
B也在执行,执行到(singleton == null)判断,那么线程B获得判断条件也是为真,于是继续
运行下去,线程A获得了一个对象,线程B也获得了一个对象,在内存中就出现两个对象!
简单点说就是,创建对象是需要时间的,当我创建的时候,第一个没有创出,那么就会出现两个对象,
这个显然的矛盾的。
懒汉模式(如果我得不到的话,并发的情况下我就会创建一个新的对象)


```java
public class Singleton {
private static Singleton singleton = null;
//限制产生多个对象
private Singleton(){
}
//通过该方法获得实例对象
public static Singleton getSingleton(){
if(singleton == null){
singleton = new Singleton();
}
return singleton;
}
}

## 7.4 单例模式的扩展
如果一个类可以产生多个对象,对象的数量不受限制,则是非常容易实现的,直接使用
new关键字就可以了,如果只需要一个对象,使用单例模式就可以了,但是如果要求一个类
只能产生两三个对象呢?该怎么实现?

一般情况下,一个朝代的同一个时代只有一个皇帝,那有没有出现两个皇帝的情况呢?
确实有,就出现在明朝,那三国期间的算不算?不算,各自称帝,各有各的地盘,国号不
同。
那么我们来扩展一下刚才的程序
![请添加图片描述](https://img-blog.csdnimg.cn/ed984fb4d72e40ff8646af7a6e2e18f0.png)

```java
public class Emperor {
//定义最多能产生的实例数量
private static int maxNumOfEmperor = 2;
//每个皇帝都有名字,使用一个ArrayList来容纳,每个对象的私有属性
private static ArrayList<String> nameList=new ArrayList<String>(); // 对于的序列号,key 
//定义一个列表,容纳所有的皇帝实例
private static ArrayList<Emperor> emperorList=new ArrayList<Emperor>();// value对象值
//当前皇帝序列号
private static int countNumOfEmperor =0; 
//产生所有的对象
static{
for(int i=0;i<maxNumOfEmperor;i++){
emperorList.add(new Emperor("皇"+(i+1)+"帝")); // 此时对象list中已经充满着对象
}
}
private Emperor(){
//世俗和道德约束你,目的就是不产生第二个皇帝
}
//传入皇帝名称,建立一个皇帝对象
private Emperor(String name){
nameList.add(name); 
}
//随机获得一个皇帝对象,共有的方法提供给外面得到一个皇帝对象,这个对象就是我从已经产生的对象List中获得
public static Emperor getInstance(){
Random random = new Random();
//随机拉出一个皇帝,只要是个精神领袖就成
countNumOfEmperor = random.nextInt(maxNumOfEmperor);
return emperorList.get(countNumOfEmperor);// 得到了countNumOfEmperor 的皇帝实例
}
//皇帝发话了
public static void say(){
System.out.println(nameList.get(countNumOfEmperor)); // 得到了countNumOfEmperor 的皇帝名字

}
}

在Emperor中使用了两个ArrayList分别存储实例和实例变量。当然,如果考虑到线程安
全问题可以使用Vector来代替。臣子参拜皇帝的过程如代码清单7-6所示。
对应的关系 名字和皇帝的实例有一下关系, 特点就是,我会产生一定数量的对象放到内存对象里面,然后使用的时候再去调用它,就可以了,不用第二次创建对象了。
请添加图片描述

代码清单7-6 臣子参拜皇帝的过程
public class Minister {
public static void main(String[] args) {
//定义5个大臣
int ministerNum =5;
for(int i=0;i<ministerNum;i++){
Emperor emperor = Emperor.getInstance();
System.out.print("第"+(i+1)+"个大臣参拜的是:");
emperor.say();
}
}
}

这种需要产生固定数量对象的模式就叫做有上限的多例模式,它是单例模式的一种扩
展,采用有上限的多例模式,我们可以在设计时决定在内存中有多少个实例。
扩展一下,关于框架的
应用也非常广泛,如在Spring中,每个Bean默
认就是单例的,这样做的优点是Spring容器可以管理这些Bean的生命期,决定什么时候创建
出来,什么时候销毁,销毁的时候要如何处理,等等。如果采用非单例模式(Prototype类
型),则Bean初始化后的管理交由J2EE容器,Spring容器不再跟踪管理Bean的生命周期。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奋斗中的代码猿--刘同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值