享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。

享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象。

概述


  • 意图

    运用共享技术有效地支持大量细粒度的对象。

  • 主要解决

    在有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。

  • 何时使用

  1. 系统中有大量对象。
  2. 这些对象消耗大量内存。
  3. 这些对象的状态大部分可以外部化。
  4. 这些对象可以按照内蕴状态分为很多组,当把外蕴对象从对象中剔除出来时,每一组对象都可以用一个对象来代替。
  5. 系统不依赖于这些对象身份,这些对象是不可分辨的。
  • 如何解决

    用唯一标识码判断,如果在内存中有,则返回这个唯一标识码所标识的对象。

  • 关键代码

    用 HashMap 存储这些对象。

  • 应用实例

  1. JAVA 中的 String,如果有则返回,如果没有则创建一个字符串保存在字符串缓存池里面。
  2. 数据库的数据池。
  3. hibernate-validate自定义了基于弱引用的缓存容器ConcurrentReferenceHashMap
  • 优点

    大大减少对象的创建,降低系统的内存,使效率提高。

  • 缺点

    提高了系统的复杂度,需要分离出外部状态和内部状态,而且外部状态具有固有化的性质,不应该随着内部状态的变化而变化,否则会造成系统的混乱。

  • 使用场景

  1. 系统有大量相似对象。
  2. 需要缓冲池的场景。
  • 注意事项
  1. 注意划分外部状态和内部状态,否则可能会引起线程安全问题。
  2. 这些类必须有一个工厂对象加以控制。

实现


摘抄hibernate-validate源码

容器:ConcurrentReferenceHashMap

调用摘抄

/**
* This manager is in charge of providing all constraint related meta data
* required by the validation engine.
* <p>
* Actual retrieval of meta data is delegated to {@link MetaDataProvider}
* implementations which load meta-data based e.g. based on annotations or XML.
* </p>
* <p>
* For performance reasons a cache is used which stores all meta data once
* loaded for repeated retrieval. Upon initialization this cache is populated
* with meta data provided by the given <i>eager</i> providers. If the cache
* doesn't contain the meta data for a requested type it will be retrieved on
* demand using the annotation based provider.
* </p>
*
* @author Gunnar Morling
* @author Chris Beckey &lt;cbeckey@paypal.com&gt;
* @author Guillaume Smet
*/
public class BeanMetaDataManager {
/**
* The default initial capacity for this cache.
*/
private static final int DEFAULT_INITIAL_CAPACITY = 16; /**
* The default load factor for this cache.
*/
private static final float DEFAULT_LOAD_FACTOR = 0.75f; /**
* The default concurrency level for this cache.
*/
private static final int DEFAULT_CONCURRENCY_LEVEL = 16; /**
* Additional metadata providers used for meta data retrieval if
* the XML and/or programmatic configuration is used.
*/
@Immutable
private final List<MetaDataProvider> metaDataProviders; /**
* Helper for builtin constraints and their validator implementations
*/
private final ConstraintHelper constraintHelper; /**
* Used for resolving generic type information.
*/
private final TypeResolutionHelper typeResolutionHelper; /**
* The {@link ValueExtractor} manager.
*/
private final ValueExtractorManager valueExtractorManager; private final ExecutableParameterNameProvider parameterNameProvider; /**
* Used to cache the constraint meta data for validated entities
*/
private final ConcurrentReferenceHashMap<Class<?>, BeanMetaData<?>> beanMetaDataCache; /**
* Used for resolving type parameters. Thread-safe.
*/
private final ExecutableHelper executableHelper; private final ValidationOrderGenerator validationOrderGenerator; /**
* the three properties in this field affect the invocation of rules associated to section 4.5.5
* of the specification. By default they are all false, if true they allow
* for relaxation of the Liskov Substitution Principal.
*/
private final MethodValidationConfiguration methodValidationConfiguration; public BeanMetaDataManager(ConstraintHelper constraintHelper,
ExecutableHelper executableHelper,
TypeResolutionHelper typeResolutionHelper,
ExecutableParameterNameProvider parameterNameProvider,
ValueExtractorManager valueExtractorManager,
ValidationOrderGenerator validationOrderGenerator,
List<MetaDataProvider> optionalMetaDataProviders,
MethodValidationConfiguration methodValidationConfiguration) {
this.constraintHelper = constraintHelper;
this.executableHelper = executableHelper;
this.typeResolutionHelper = typeResolutionHelper;
this.valueExtractorManager = valueExtractorManager;
this.parameterNameProvider = parameterNameProvider;
this.validationOrderGenerator = validationOrderGenerator; this.methodValidationConfiguration = methodValidationConfiguration; this.beanMetaDataCache = new ConcurrentReferenceHashMap<>(
DEFAULT_INITIAL_CAPACITY,
DEFAULT_LOAD_FACTOR,
DEFAULT_CONCURRENCY_LEVEL,
SOFT,
SOFT,
EnumSet.of( IDENTITY_COMPARISONS )
); AnnotationProcessingOptions annotationProcessingOptions = getAnnotationProcessingOptionsFromNonDefaultProviders( optionalMetaDataProviders );
AnnotationMetaDataProvider defaultProvider = new AnnotationMetaDataProvider(
constraintHelper,
typeResolutionHelper,
valueExtractorManager,
annotationProcessingOptions
);
List<MetaDataProvider> tmpMetaDataProviders = new ArrayList<>( optionalMetaDataProviders.size() + 1 );
// We add the annotation based metadata provider at the first position so that the entire metadata model is assembled
// first.
// The other optional metadata providers will then contribute their additional metadata to the preexisting model.
// This helps to mitigate issues like HV-1450.
tmpMetaDataProviders.add( defaultProvider );
tmpMetaDataProviders.addAll( optionalMetaDataProviders ); this.metaDataProviders = CollectionHelper.toImmutableList( tmpMetaDataProviders );
} @SuppressWarnings("unchecked")
public <T> BeanMetaData<T> getBeanMetaData(Class<T> beanClass) {
Contracts.assertNotNull( beanClass, MESSAGES.beanTypeCannotBeNull() ); BeanMetaData<T> beanMetaData = (BeanMetaData<T>) beanMetaDataCache.computeIfAbsent( beanClass,
bc -> createBeanMetaData( bc ) ); return beanMetaData;
} public void clear() {
beanMetaDataCache.clear();
} public int numberOfCachedBeanMetaDataInstances() {
return beanMetaDataCache.size();
}
}

设计模式学习心得<享元模式 Flyweight>的更多相关文章

  1. 设计模式学习心得<代理模式 Proxy>

    在代理模式(Proxy Pattern)中,一个类代表另一个类的功能.这种类型的设计模式属于结构型模式. 在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口. 概述 意图 为其他对象提供 ...

  2. 设计模式系列之代理模式(Proxy Pattern)——对象的间接访问

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

  3. 设计模式学习之代理模式(Proxy,结构型模式)(11)

    参考地址:http://www.cnblogs.com/zhili/p/ProxyPattern.html 一.引言 在软件开发过程中,有些对象有时候会由于网络或其他的障碍,以至于不能够或者不能直接访 ...

  4. 设计模式学习之代理模式(Proxy)

    一.代理模式的初衷 不想让客户端直接访问具体实现接口,客户端不应该直接访问具体实现,一般会涉及到以下四个对象 业务接口:定义客户端访问的接口,是实现类和代理类都需要实现的 实现类:实现了业务接口,真正 ...

  5. Java设计模式学习记录-代理模式

    代理模式 代理模式是常见设计模式的一种,代理模式的定义是:为其他对象提供一种代理以控制对这个对象的访问. 在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起 ...

  6. 设计模式入门之代理模式Proxy

    //代理模式定义:为其它对象提供一种代理以控制对这个对象的訪问 //实例:鉴于书中给出的样例不太好.并且有些疑问,所以直接用保护代理作为实例 //要求,一旦订单被创建,仅仅有订单的创建人才干够改动订单 ...

  7. 学习笔记——代理模式Proxy

    代理模式,主要是逻辑和实现解耦.具体逻辑如何,由代理Proxy自己来设计,我们只需要把逻辑Subject交给代理即可. 主要应用场景,包括创建大开销对象时,使用代理来慢慢创建:远程代理,如网络不确定时 ...

  8. 《JAVA设计模式》之代理模式(Proxy)

    在阎宏博士的<JAVA与模式>一书中开头是这样描述代理(Proxy)模式的: 代理模式是对象的结构模式.代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用. 代理模式的结 ...

  9. javascript设计模式学习之六——代理模式

    一.代理模式定义 代理模式的关键是:当客户不方便直接访问一个对象或者不满足需要的时候,提供一个替身对象来控制对这个对象的访问.代理模式需要和本体对外提供相同的接口,对用户来说是透明的.代理模式的种类有 ...

  10. 设计模式学习心得<组合模式 Composite>

    组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象.组合模式依据树形结构来组合对象,用来表示部分以及整体层次.这种类型的设计模式属于结构型模式, ...

随机推荐

  1. Logparser介绍

    原文链接:https://www.cnblogs.com/Jerseyblog/p/3986591.html Logparser是一款非常强大的日志分析软件,可以帮助你详细的分析网站日志.是所有数据分 ...

  2. jQuery+php+Ajax文章列表点击加载更多功能

    jQuery+php+Ajax实现的一个简单实用的文章列表点击加载更多功能,点击加载更多按钮,文章列表加载更多数据,加载中有loading动画效果. js部分: <script type=&qu ...

  3. django后台admin csv 格式表格导出

    1.在app下新建一个.py文件  此例commen.py commen.py (内容)(具体怎么导出的也不知道这么写就对了) import csv from django.http import H ...

  4. SpringCloud系列八:Zuul 路由访问(Zuul 的基本使用、Zuul 路由功能、zuul 过滤访问、Zuul 服务降级)

    1.概念:Zuul 路由访问 2.具体内容 在现在为止所有的微服务都是通过 Eureka 找到的,但是在很多的开发之中为了规范微服务的使用,提供有一个路由的处理控制组件:Zuul,也就是说 Zuul ...

  5. azkaban使用--schedule定时任务

    1.schedule azkaban的schedule内部就是集成的quartz,而 quartz语法就是沿用linux crontab,crontab可照本文第2点 此处以此project(azka ...

  6. thinkphp5.1明明密码的一致的 却说不一致的解决办法

    protected $rule = [       'password|密码'=>[                       'require',           'length:6,2 ...

  7. MyEclipse Web项目部署失败:Deployment failure on Tomcat 7.x.Could not copy all resources to XXX.

    在做第一个MyEclipse web项目时,总是部署失败: Deployment failure on Tomcat 7.x.Could not copy all resources to XXX.I ...

  8. React 获取服务器API接口数据:axios、fetchJsonp

    使用axios.fetchJsonp获取服务器的接口数据.其中fetchJsonp是跨域访问 一.使用axios 1.安装axios模块 npm install --save axios 2.引用模块 ...

  9. alias命令详解

    1.简介: 设置指令的别名,用户可利用alias,自定指令的别名.若仅输入alias,则可列出目前所有的别名设置. alias的效力仅及于该次登入的操作.若要每次登入是即自动设好别名,可在/etc/p ...

  10. 开启mysql-binlog日志操作步骤

    步骤1:找到mysql主库的配置文件(注意:不能为从库),lunix系统路径一般为/etc/my.cnf 步骤2:修改配置文件(可以提前备份一下)以开启mysql-binlog功能.添加以下3行: l ...