享元模式适用于需要大量相同类型对象的情况。在此,设计布局可以减少创建多个对象的方式。对象在运行时会消耗资源,因此最好在内存中使用较少的对象。它减少了内存占用并利用了程序的整体性能。本文是在学习完优锐课JAVA架构VIP课程—【框架源码专题】中《学习源码中的优秀设计模式》后写下的学习感悟。通过Java中的一个简单示例深入研究了这种模式。

深入探索Java设计模式(一)之单例模式

深入探索Java设计模式(二)之策略模式

深入探索Java设计模式(三)之装饰器模式

总览

轻量级模式减少了重复数据的使用。通常的做法是将对象设计成细粒度以利用其使用的灵活性。但是,问题是对象在运行时会消耗资源。粒度会不利地影响应用程序的性能,因为需要将运行时对象容纳在更大的内存集中。每个对象不仅消耗内存,而且消耗CPU周期。在这种情况下,轻量化模式可以通过减少细粒度对象的重复实例化来解决。

享元模式Flyweight Pattern

享元模式分为两部分:

  • 内部的:这是独立的部分,数据存储在对象中,与享元模式上下文无关。结果,它对于所有相同的固有数据都是可共享的,因此可以用享元模式对象替换。
  • 外在的: 这是从属部分,其中保留了举重对象的上下文信息。这是不可共享的。状态由客户端对象存储,并根据要求传递给享元模式对象。

享元模式的使用

在我们有许多表示相同值的对象的情况下,这很有用。因此,它使不可变对象的值可共享。例如,在下面的代码片段中观察Java标准库的Integer包装器类的valueOf()方法如何检查给定参数的值。

 public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}

如果该值先前已缓存,则该方法将返回构造函数实例,而不是创建一个新对象。因为缓存是在静态块中初始化的,所以仅在第一次调用时才创建Integer实例。请注意,IntegerCache类是在Integerclass中定义的私有静态类。

 private static class IntegerCache {
// ...
static {
// ...
cache = new Integer[(high - low) + 1];
int j = low;
for (int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// Range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
// ...
}

现在,我们可以测试Integer类是否创建两个不同的对象(如果值相同)。将图1中的输出与以下代码进行比较。

 public class JustForTesting {
public static void main(String[] args){
final Integer intObj1 = Integer.valueOf(10);
final Integer intObj2 = Integer.valueOf(10);
System.out.println("First Case");
if (intObj1 == intObj2){
System.out.println("If the values are same " +
"then the objects are also same.");
} else {
System.out.println("If the values are different " +
"then the objects are also distinct.");
}
// Now, if we change the same value to a different
// value, it becomes two distinct objects final Integer intObj3 = Integer.valueOf(10);
final Integer intObj4 = Integer.valueOf(20);
System.out.println("Second Case");
if (intObj3 == intObj4){
System.out.println("If the values are same " +
"then the objects are also same.");
} else {
System.out.println("If the values are different " +
"then the objects are also distinct.");
}
}
}

输出

1:前面代码的输出

实现享元模式

这是享元模式的简单实现。观察如何限制具有相同值的对象创建新对象,而不是提供池中已经存在的对象的副本。工厂中的对象池充当保留享元模式实例的缓存。

 package testpattern;
public class Car {
private String color;
public Car(String color){
this.color = color;
System.out.println("Painted with "+color+" color.");
}
public String getColor() {
return color;
}
}
package testpattern;
import java.util.ArrayList;
import java.util.List;
public class CarFactory {
private List<Car> carpool = new ArrayList<>();
public Car getFlyweightCar(String color) {
for (Car c: carpool) {
if (c.getColor().equals(color)){
System.out.println(color +
" car is already in the pool!");
return c;
}
}
Car car = new Car(color);
carpool.add(car);
return car;
}
}
package testpattern;
public class App {
public static void main(String[] args) {
CarFactory cf = new CarFactory();
cf.getFlyweightCar("RED");
cf.getFlyweightCar("BLUE");
cf.getFlyweightCar("GREEN");
cf.getFlyweightCar("PURPLE");
cf.getFlyweightCar("RED");
cf.getFlyweightCar("BLUE");
cf.getFlyweightCar("BLACK");
}
}

输出

2:享元模式实现的输出

结论

享元模式是在许多情况下使用的常见模式,有时程序员会在不知不觉中使用它。这种模式说明了我们如何使用许多内存不足的对象。如前所述,我们必须始终尽可能利用不变的Integer类的valueOf方法,因为当我们调用new时,即使缓存包含相同的对象,也会创建一个新实例。正如我们已经讨论过的那样,valueOf方法还可以工作。这是使用享元模式的优势。

感谢阅读!欢迎留言。想更深入探讨学习也欢迎私信我。下篇继续~

深入探索Java设计模式(五)之构建器模式

深入探索Java设计模式(四)之享元模式的更多相关文章

  1. Java设计模式之《享元模式》及应用场景

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6542449.html 享元模式:"享"就是分享之意,指一物被众人共享, ...

  2. 重学 Java 设计模式:实战享元模式「基于Redis秒杀,提供活动与库存信息查询场景」

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 程序员‍‍的上下文是什么? 很多时候一大部分编程开发的人员都只是关注于功能的实现,只 ...

  3. Java设计模式学习记录-享元模式

    前言 享元模式也是一种结构型模式,这篇是介绍结构型模式的最后一篇了(因为代理模式很早之前就已经写过了).享元模式采用一个共享来避免大量拥有相同内容对象的开销.这种开销最常见.最直观的就是内存损耗. 享 ...

  4. 【转】Java设计模式之《享元模式》及应用场景

    享元模式:“享”就是分享之意,指一物被众人共享,而这也正是该模式的终旨所在. 享元模式有点类似于单例模式,都是只生成一个对象来被共享使用.这里有个问题,那就是对共享对象的修改,为了避免出现这种情况,我 ...

  5. java设计模式-----10、享元模式

    Flyweight模式也叫享元模式,是构造型模式之一,它通过与其他类似对象共享数据来减小内存占用.它使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件:它适合用于只是因重复而导致使 ...

  6. Java设计模式:Flyweight(享元)模式

    概念定义 享元(Flyweight)模式运用共享技术高效地支持大量细粒度对象的复用. 当系统中存在大量相似或相同的对象时,有可能会造成内存溢出等问题.享元模式尝试重用现有的同类对象,如果未找到匹配的对 ...

  7. 《JAVA设计模式》之享元模式(Flyweight)

    在阎宏博士的<JAVA与模式>一书中开头是这样描述享元(Flyweight)模式的: Flyweight在拳击比赛中指最轻量级,即“蝇量级”或“雨量级”,这里选择使用“享元模式”的意译,是 ...

  8. Java描述设计模式(18):享元模式

    本文源码:GitHub·点这里 || GitEE·点这里 一.使用场景 应用代码 public class C01_InScene { public static void main(String[] ...

  9. 设计模式系列之享元模式(Flyweight Pattern)——实现对象的复用

    说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...

  10. 设计模式学习之享元模式(Flyweight,结构型模式)(20)

    转:http://terrylee.cnblogs.com/archive/2006/03/29/361767.html 摘要:面向对象的思想很好地解决了抽象性的问题,一般也不会出现性能上的问题.但是 ...

随机推荐

  1. 手摸手带你认识https涉及的知识,并实现https加密解密,加签解签

    目录 http访问流程 https访问流程 证书 加密/解密 加签/验签 Java实现https 拓展 @ 看完整的代码,直接去完整代码实现,看实现完后会遇到的坑,直接去测试过程中的问题,包括经过代理 ...

  2. JavaScript笔记八

    1.原型(prototype) - 创建一个函数以后,解析器都会默认在函数中添加一个数prototype prototype属性指向的是一个对象,这个对象我们称为原型对象. - 当函数作为构造函数使用 ...

  3. WebGL简易教程(十三):帧缓存对象(离屏渲染)

    目录 1. 概述 2. 示例 2.1. 着色器部分 2.2. 初始化/准备工作 2.2.1. 着色器切换 2.2.2. 帧缓冲区 2.3. 绘制函数 2.3.1. 初始化顶点数组 2.3.2. 传递非 ...

  4. NLog日志框架使用探究-2

    目录 前言 自定义参数 日志输出方式 文件 网络传输 数据库 科学使用 参考文档 前言 在一年前,我写过一篇关于NLog入门文章<NLog日志框架使用探究-1>,文章简单的介绍了Nlog的 ...

  5. Linux发展史及安装

    操作系统 什么是操作系统 人与硬件的中介/桥梁 操作系统的组成  操作系统可以理解为一个鸡蛋 蛋黄    内核                   Linux内核  托瓦斯  鸡蛋清  命令解释器(s ...

  6. 灵魂拷问:为什么 Java 字符串是不可变的?

    在逛 programcreek 的时候,发现了一些精妙绝伦的主题.比如说:为什么 Java 字符串是不可变的?像这类灵魂拷问的主题,非常值得深思. 对于绝大多数的初级程序员来说,往往停留在" ...

  7. PHP如何获取视频总时长与码率等信息

    利用PHP中的FFmpeg读取视频播放时长与码率等信息   function getVideoInfo($file) {    define('FFMPEG_PATH', '/usr/local/ff ...

  8. centos7安装fail2ban

    fail2ban是一款非常实用的安全软件,通过监视系统日志,设置错误登陆次数,可阻挡暴力密码攻击. 1.安装epelyum install epel-release -y 2.安装fail2banyu ...

  9. pycharm启动vue项目

    一 移动vue项目问题 1 移植到其他windows or mac 2 重新安装依赖 基于情况2(我们把除了第一个文件都复制到一个新的文件夹) 重新依据配置文件去安装各种各样的依赖(也就是根据配置文件 ...

  10. 关于jsp页面的复选框(checkbox)取值的获取问题

    复选框的取值问题可以使用js和jQuery来获取: jQuery API : each(callback) :以每一个匹配的元素作为上下文来执行一个函数. :checked :匹配所有选中的被选中元素 ...