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) 推荐大家访问学习

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
单例模式:某个类只能有一个实例,提供一个全局的访问点。 简单工厂:一个工厂类根据传入的参量决定创建出那一种产品类的实例。 工厂方法:定义一个创建对象的接口,让子类决定实例化那个类。 抽象工厂:创建相关或依赖对象的家族,而无需明确指定具体类。 建造者模式:封装一个复杂对象的构建过程,并可以按步骤构造。 原型模式:通过复制现有的实例来创建新的实例。 适配器模式:将一个类的方法接口转换成客户希望的另外一个接口。 组合模式:将对象组合成树形结构以表示“”部分-整体“”的层次结构。 装饰模式:动态的给对象添加新的功能。 代理模式:为其他对象提供一个代理以便控制这个对象的访问。 亨元(蝇量)模式:通过共享技术来有效的支持大量细粒度的对象。 外观模式:对外提供一个统一的方法,来访问子系统中的一群接口。 桥接模式:将抽象部分和它的实现部分分离,使它们都可以独立的变化。 模板模式:定义一个算法结构,而将一些步骤延迟到子类实现。 解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器。 策略模式:定义一系列算法,把他们封装起来,并且使它们可以相互替换。 状态模式:允许一个对象在其对象内部状态改变时改变它的行为。 观察者模式:对象间的一对多的依赖关系。 备忘录模式:在不破坏封装的前提下,保持对象的内部状态。 中介者模式:用一个中介对象来封装一系列的对象交互。 命令模式:将命令请求封装为一个对象,使得可以用不同的请求来进行参数化。 访问者模式:在不改变数据结构的前提下,增加作用于一组对象元素的新功能。 责任链模式:将请求的发送者和接收者解耦,使的多个对象都有处理这个请求的机会。 迭代器模式:一种遍历访问聚合对象中各个元素的方法,不暴露该对象的内部结构。
设计模式是一种常用的软件设计方法,用于解决特定问题的方案。在面向对象的软件开发中,有一些经典的设计模式,其中23种是最为常见的。以下是对这23设计模式的简要UML图解释: 1. 简单工厂模式(Simple Factory Pattern):通过一个工厂类来创建不同类型的对象。 2. 工厂方法模式(Factory Method Pattern):定义一个创建对象的接口,由子类来决定具体实例化的对象。 3. 抽象工厂模式(Abstract Factory Pattern):提供一个创建相关或依赖对象家族的接口,而无需指定具体类。 4. 单例模式(Singleton Pattern):确保一个类只有一个实例,并提供全局访问点。 5. 原型模式(Prototype Pattern):通过复制已有对象来创建新对象。 6. 建造者模式(Builder Pattern):将一个复杂对象的构建与其表示分离,使同样的构建过程可以创建不同的表示。 7. 适配器模式(Adapter Pattern):将一个类的接口转换成客户端希望的另一个接口。 8. 桥接模式(Bridge Pattern):将抽象部分与实现部分分离,使它们可以独立变化。 9. 组合模式(Composite Pattern):将对象组合成树形结构以表示"部分-整体"的层次结构。 10. 装饰器模式(Decorator Pattern):动态地给对象添加额外的职责。 11. 外观模式(Facade Pattern):为子系统中的一组接口提供一个统一的接口。 12. 享元模式(Flyweight Pattern):使用共享对象来有效地支持大量细粒度的对象。 13. 代理模式(Proxy Pattern):为其他对象提供一种代理以控制对这个对象的访问。 14. 责任链模式(Chain of Responsibility Pattern):将请求的发送者和接收者解耦,使多个对象都有机会处理这个请求。 15. 命令模式(Command Pattern):将请求封装成一个对象,并且可以用不同的请求来参数化其他对象。 16. 解释器模式(Interpreter Pattern):给定一个语言,定义它的文法的一种表示,并定义一个解释器,通过使用该解释器来解释语言中的句子。 17. 迭代器模式(Iterator Pattern):提供一种方法顺序访问一个容器对象中的各个元素,而又不暴露其内部的表示。 18. 中介者模式(Mediator Pattern):用一个中介对象来封装一系列对象之间的交互。 19. 备忘录模式(Memento Pattern):在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。 20. 观察者模式(Observer Pattern):定义了一种一对多的依赖关系,使得当一个对象改变状态时,所有依赖它的对象都会被通知并自动更新。 21. 状态模式(State Pattern):允许对象在其内部状态改变时改变它的行为。 22. 策略模式(Strategy Pattern):定义一系列的算法,将每个算法都封装起来,并使它们之间可以互换。 23. 模板方法模式(Template Method Pattern):定义一个操作中的算法的骨架,将一些步骤延迟到子类中实现。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

程序员小牧之

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

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

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

打赏作者

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

抵扣说明:

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

余额充值