深入探索Java设计模式(四)之享元模式
享元模式适用于需要大量相同类型对象的情况。在此,设计布局可以减少创建多个对象的方式。对象在运行时会消耗资源,因此最好在内存中使用较少的对象。它减少了内存占用并利用了程序的整体性能。本文是在学习完优锐课JAVA架构VIP课程—【框架源码专题】中《学习源码中的优秀设计模式》后写下的学习感悟。通过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设计模式之《享元模式》及应用场景
原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6542449.html 享元模式:"享"就是分享之意,指一物被众人共享, ...
- 重学 Java 设计模式:实战享元模式「基于Redis秒杀,提供活动与库存信息查询场景」
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 程序员的上下文是什么? 很多时候一大部分编程开发的人员都只是关注于功能的实现,只 ...
- Java设计模式学习记录-享元模式
前言 享元模式也是一种结构型模式,这篇是介绍结构型模式的最后一篇了(因为代理模式很早之前就已经写过了).享元模式采用一个共享来避免大量拥有相同内容对象的开销.这种开销最常见.最直观的就是内存损耗. 享 ...
- 【转】Java设计模式之《享元模式》及应用场景
享元模式:“享”就是分享之意,指一物被众人共享,而这也正是该模式的终旨所在. 享元模式有点类似于单例模式,都是只生成一个对象来被共享使用.这里有个问题,那就是对共享对象的修改,为了避免出现这种情况,我 ...
- java设计模式-----10、享元模式
Flyweight模式也叫享元模式,是构造型模式之一,它通过与其他类似对象共享数据来减小内存占用.它使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件:它适合用于只是因重复而导致使 ...
- Java设计模式:Flyweight(享元)模式
概念定义 享元(Flyweight)模式运用共享技术高效地支持大量细粒度对象的复用. 当系统中存在大量相似或相同的对象时,有可能会造成内存溢出等问题.享元模式尝试重用现有的同类对象,如果未找到匹配的对 ...
- 《JAVA设计模式》之享元模式(Flyweight)
在阎宏博士的<JAVA与模式>一书中开头是这样描述享元(Flyweight)模式的: Flyweight在拳击比赛中指最轻量级,即“蝇量级”或“雨量级”,这里选择使用“享元模式”的意译,是 ...
- Java描述设计模式(18):享元模式
本文源码:GitHub·点这里 || GitEE·点这里 一.使用场景 应用代码 public class C01_InScene { public static void main(String[] ...
- 设计模式系列之享元模式(Flyweight Pattern)——实现对象的复用
说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...
- 设计模式学习之享元模式(Flyweight,结构型模式)(20)
转:http://terrylee.cnblogs.com/archive/2006/03/29/361767.html 摘要:面向对象的思想很好地解决了抽象性的问题,一般也不会出现性能上的问题.但是 ...
随机推荐
- SpringBoot学习(三)—— springboot快速整合swagger文档
目录 MyBatis 简介 引入mybatis组件 代码实战 MyBatis @ 简介 优点 最大的优点是SQL语句灵活,适合调优情景,业务复杂情景 劣势 最大的劣势是不同数据库之间的迁移 引入myb ...
- Linux基础命令复习01
一.Linux中的基本查看.查找命令: 1.ls 查看目录信息: -l #查看属性,以长格式显示 -d #查看本身属性 -A #显示包括以.开头的隐藏文档 -h #提供易读的单位 -R #表示递 ...
- Docker从入门到实践(4-1)
使用 Docker 镜像 在之前的介绍中,我们知道镜像是 Docker 的三大组件之一. Docker 运行容器前需要本地存在对应的镜像,如果本地不存在该镜像,Docker 会从镜像仓库下载该镜像. ...
- Rust 入门 (一)
Rust 语言的介绍.特性什么的都不说了,如有需要,请自行了解.这里我们直接进去正题. 一.开发环境 mac或linux系统,在命令行安装 curl https://sh.rustup.rs -sSf ...
- python与redis交互及redis基本使用
Redis简介 Redis是一使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日个开源的志型.Key-Value数据库,并提供多种语言的API. 从2010年3月15日起,Redis的开发工 ...
- nginx实现前后台分离部署
2.1 前后台分离部署 (一) 组网图 (二) 简要说明: 如标题所示,至于为什么要前后台分离部署,个人理解的原因有三 (一) 便于部署 前台代码由ngin ...
- JDK动态代理和CGLIB字节码增强
一.JDK动态代理 Java 在 java.lang.reflect 包中有自己的代理支持,该类(Proxy.java)用于动态生成代理类,只需传入目标接口.目标接口的类加载器以及 Invocatio ...
- python-面向对象之封装
封装 面向对象三大特性: 继承 封装 多态 隐藏对象的属性和实现细节,仅对外提供公共访问方法 广义上的封装 : 把方法和变量都封装在类中 狭义上的封装 : 在类的外部干脆不能调用了 优点 将变化隔离 ...
- 【JavaEE】之MyBatis开发DAO
在SSM框架中的DAO层就是MyBatis中的Mapper,Mapper分为两部分:Mapper接口(JAVA文件)和Mapper映射文件(XML文件).DAO开发(Mapper开发)有两种方式:原始 ...
- flask-简介
什么是flask? Flask简介: Flask是一个Python编写的Web 微框架,让我们可以使用Python语言快速实现一个网站或Web服务,在介绍Flask之前首先来聊下它和Django的联系 ...
