23.共享模式

1.什么是共享模式?

共享模式是一种结构型设计模式,它丢弃了在每个对象中保存所有数据的方式,通过共享多个对象所共有的相同状态,让我们能在有限的内存容量中载入更多的对象。

1.1 共享模式解决的问题

首先抛出一个问题:
假如我们要开发一个真实的粒子系统,开发完成后, 你推送提交了最新版本的程序, 并在编译后将其发送给了一个朋友进行测试。 尽管该游戏在你的电脑上完美运行, 但是你的朋友却无法长时间进行: 粒子系统总是会在他的电脑上运行几分钟后崩溃。 在研究了几个小时的调试消息记录后, 你发现导致程序崩溃的原因是内存容量不足。 朋友的设备性能远比不上你的电脑, 因此游戏运行在他的电脑上时很快就会出现问题。
真正的问题与粒子系统有关。 每个粒子 都由包含完整数据的独立对象来表示。 当程序运行导某一时刻, 粒子系统将无法在剩余内存中载入新建粒子, 于是程序就崩溃了。

1.1.1 重现上面的问题

下面我们来做一个粒子系统并重现上面的问题(内存消耗严重):
参考博客: Java粒子系统(烟花篇)_DwLuffy的博客-CSDN博客
在这里插入图片描述

在这里插入图片描述

可以看到现在的内存消耗已经突破1G了,对于这样的一个小程序,这样的内存消耗是不是有点太大了。

通过检查程序我们发现主要问题在这里:

while (true) {
    // 画背景
    g = panel.getGraphics();
    // 生成粒子放入链表
    Particle tp = new Particle();
    tp.position = new VecT(startX, startY);
    tp.velocity = new VecT(10, -20);// 速度向量
    tp.acceleration = sampleDirection();
    tp.life = 30;
    tp.age = 1;
    tp.color = new Color(255, 0, 255);
    tp.size = 12;
    particleArrayList.add(tp);
    }

在程序里的循环里不断新建Particle对象,且Partcle中的成员也都是用新建对象的方式来填充的,而新建这样的对象进行使用是需要内存的。
代码地址如下:设计模式/src/main/java/FlyweightPattern/first · 严家豆/Head first 设计模式学习 - 码云 - 开源中国 (gitee.com)
那么如何解决呢? 答案是共享模式,我们可以用共享模式对这个问题进行解决。

1.2 解决方案: 共享模式

通过观察上面的代码,我们发现每次新建Particle对象都会重新创建一些相同的VecT对象和Color对象。

我们是不是可以通过共享模式:丢弃在每个对象中保存所有数据的方式,通过共享多个对象所共有的相同状态,让我们能在有限的内存容量中载入更多的对象。 来节省内存使用
也就是说,对于那些已知取值范围且可列举的部分对象(不变),我们可以使用先创建,然后使用引用的方式将其填充到新建的对象中。
以Color为例,我们可以像下面这样做:

private final List<Color> colorList = new ArrayList<>();
//先创建10个Color对象
for(int i=0;i<10;i++){
    int r = c.getRGB();
    colorList.add(new Color((int) (r-(int)1000*(Math.random()))));
}
//需要Color对象的时候,直接根据随机条件进行取出,无需创建
tp.color = colorList.get((int) (Math.random() * 10));

这样的话,我们就可以减少new Color()的次数,从而减少内存的占用,也能达到和前面相同的效果。
在这里插入图片描述

地址如下:
设计模式/src/main/java/FlyweightPattern/betterFirst · 严家豆/Head first 设计模式学习 - 码云 - 开源中国 (gitee.com)

最后本文的内容主要吸收总结与一个很好的设计模式学习网站:
设计模式学习网站 (refactoringguru.cn) 推荐大家访问学习

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

程序员小牧之

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

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

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

打赏作者

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

抵扣说明:

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

余额充值