Flyweight模式也叫享元模式,是构造型模式之一,它通过与其他类似对象共享数据来减小内存占用。它使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件;它适合用于只是因重复而导致使用无法令人接受的大量内存的大量物件。通常物件中的部分状态是可以分享。常见做法是把它们放在外部数据结构,当需要使用时再将它们传递给享元。 

  享元模式的角色和职责

    1、抽象享元角色:为具体享元角色规定了必须实现的方法,而外蕴状态就是以参数的形式通过此方法传入。在Java中可以由抽象类、接口来担当

    2、具体享元角色:实现抽象角色规定的方法。如果存在内蕴状态,就负责为内蕴状态提供存储空间。

    3、享元工厂角色:负责创建和管理享元角色。要想达到共享的目的,这个角色的实现是关键。

    4、客户端角色   :维护对所有享元对象的引用,而且还需要存储对应的外蕴状态。

  两个状态

    1、内蕴状态存储在享元内部,不会随环境的改变而有所不同,是可以共享的
    2、外蕴状态是不可以共享的,它随环境的改变而改变的,因此外蕴状态是由客户端来保持(因为环境的变化是由客户端引起的)。

  下面举个小例子

  首先,创建一个抽象享元角色

 public interface Flyweight {
public void display();
}

  接着,创建具体享元角色

 public class MyFlyweight implements Flyweight{
private String str; public MyFlyweight(String str){
this.str = str;
} public void display(){
System.out.println(str);
}
}  

  如果,不使用享元模式的话,不创建享元工厂,直接,创建客户端,代码如下:

 public class MainClass {
public static void main(String[] args) {
Flyweight myFlyweight1 = new MyFlyweight("a");
Flyweight myFlyweight2 = new MyFlyweight("b");
Flyweight myFlyweight3 = new MyFlyweight("a");
Flyweight myFlyweight4 = new MyFlyweight("d"); myFlyweight1.display();
myFlyweight2.display();
myFlyweight3.display();
myFlyweight4.display(); System.out.println(myFlyweight1 == myFlyweight3);
}
}

  这样子,运行结果为:

  这样子,可以看到,第一个与第三个明明都是a,但却不是同一个对象,说明虽然对象内部一模一样,但却创建了两个对象,这样就浪费了资源。

  如果用到享元模式,继续创建享元工厂

 public class MyFlyweightFactory {
private Map<String,MyFlyweight> pool; public MyFlyweightFactory(){
pool = new HashMap<String,MyFlyweight>();
} public Flyweight getMyFlyweight(String str){
MyFlyweight myFlyweight = pool.get(str); //若池中没有则创建一个新的并放入池中,若池中已存在,则返回池中的
if(myFlyweight == null){
myFlyweight = new MyFlyweight(str);
pool.put(str, myFlyweight);
} return myFlyweight;
}
}

  这样,修改客户端

 public class MainClass {
public static void main(String[] args) {
MyFlyweightFactory myFlyweightFactory = new MyFlyweightFactory();
Flyweight myFlyweight1 = myFlyweightFactory.getMyFlyweight("a");
Flyweight myFlyweight2 = myFlyweightFactory.getMyFlyweight("b");
Flyweight myFlyweight3 = myFlyweightFactory.getMyFlyweight("a");
Flyweight myFlyweight4 = myFlyweightFactory.getMyFlyweight("d"); myFlyweight1.display();
myFlyweight2.display();
myFlyweight3.display();
myFlyweight4.display(); System.out.println(myFlyweight1 == myFlyweight3);
}
}

  此时,结果就变为了

  可以看到,第一个与第三个变为了同一个对象,一模一样的对象只创建一次,节约了资源,这样,享元模式的作用就达到了。

  使用场景

  如果一个应用程序使用了大量的对象,而这些对象造成了很大的存储开销的时候就可以考虑是否可以使用享元模式。
例如,如果发现某个对象的生成了大量细粒度的实例,并且这些实例除了几个参数外基本是相同的,如果把那些共享参数移到类外面,在方法调用时将他们传递进来,就可以通过共享大幅度单个实例的数目。
  

java设计模式-----10、享元模式的更多相关文章

  1. Java设计模式之七 ----- 享元模式和代理模式

    前言 在上一篇中我们学习了结构型模式的组合模式和过滤器模式.本篇则来学习下结构型模式最后的两个模式, 享元模式和代理模式. 享元模式 简介 享元模式主要用于减少创建对象的数量,以减少内存占用和提高性能 ...

  2. 11.java设计模式之享元模式

    基本需求: 小型的外包项目,给客户A做一个产品展示网站,客户A的朋友感觉效果不错,也希望做这样的产品展示网站,但是要求都有些不同 每个客户要求发布的方式不一样,A要求以新闻的方式发布,B要求以博客的方 ...

  3. JAVA设计模式之享元模式

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

  4. 由奶茶店突发奇想开始了Java设计模式:享元模式

    目录 定义 意图 主要解决问题 何时使用 优缺点 结构 奶茶摊位的例子 奶茶店的例子 在什么情况下使用享元模式 定义 享元模式是对象的结构模式,享元模式以共享的方式高效的支持大量的细粒度对象,主要用于 ...

  5. python设计模式之享元模式

    python设计模式之享元模式 由于对象创建的开销,面向对象的系统可能会面临性能问题.性能问题通常在资源受限的嵌入式系统中出现,比如智能手机和平板电脑.大型复杂系统中也可能会出现同样的问题,因为要在其 ...

  6. 乐在其中设计模式(C#) - 享元模式(Flyweight Pattern)

    原文:乐在其中设计模式(C#) - 享元模式(Flyweight Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 享元模式(Flyweight Pattern) 作者:weba ...

  7. Java进阶篇设计模式之七 ----- 享元模式和代理模式

    前言 在上一篇中我们学习了结构型模式的组合模式和过滤器模式.本篇则来学习下结构型模式最后的两个模式, 享元模式和代理模式. 享元模式 简介 享元模式主要用于减少创建对象的数量,以减少内存占用和提高性能 ...

  8. Java设计模式15:常用设计模式之享元模式(结构型模式)

    1. Java之享元模式(Flyweight Pattern) (1)概述:       享元模式是对象池的一种实现,英文名为"Flyweight",代表轻量级的意思.享元模式用来 ...

  9. 设计模式(C#)——10享元模式

    推荐阅读:  我的CSDN  我的博客园  QQ群:704621321 前言       在软件开发中,当我们需要对某些对象重复创建,且最终只需要得到单一结果.如果使用一般思维,那我们将浪费很多内存空 ...

  10. 【GOF23设计模式】享元模式

    来源:http://www.bjsxt.com/ 一.[GOF23设计模式]_享元模式.享元池.内部状态.外部状态.线程池.连接池 package com.test.flyweight; /** * ...

随机推荐

  1. Statement与PreparedStatement区别

    1.性能区别 Statement statement = conn.createStatement(); PreparedStatement preStatement = conn.prepareSt ...

  2. Navicat 12破解工具 +安装包

    下载地址: https://www.lanzous.com/b657322/ 密码:1j9x zip解压密码:gubin 下载完成 是这样的  先安装第一个  安装完成后 不要打开 ,把第二个复制到安 ...

  3. C++中vector的使用

    在c++中,vector是一个十分有用的容器. 作用:它能够像容器一样存放各种类型的对象,简单地说,vector是一个能够存放任意类型的动态数组,能够增加和压缩数据. vector在C++标准模板库中 ...

  4. WEB-INFO 目录

    WEB-INF下面的内容都是只能由服务器级别才能访问,客户端并不能访问. 转发就是服务器级别,浏览器的地址不会变,因为,客户端发送一个请求,服务器受理之后,发现要请求内容还要再去别的请求,那么转发就是 ...

  5. Python小白学习之路(二十二)—【生成器】

    一.什么是生成器? 生成器可以理解成是一种数据类型,特殊地是生成器可以自动实现迭代器协议其他的数据类型需要调用自己内置的__iter__方法所以换种说法,生成器就是可迭代对象 !回忆:很重要的迭代器协 ...

  6. Vim实用技巧系列 - 开篇

    作者使用Vim已经有一段时间了,深深觉得它是一个非常强大的编辑器,使用习惯之后效率很高.最大的缺点是学习曲线比较陡峭.因此作者希望分享一些自己在实际使用中的经验来帮助初学者,同时也帮助作者自己学习. ...

  7. org.apache.ibatis.executor.loader.javassist.JavassistProxyFactory$EnhancedResultObjectProxyImpl and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.

    当我用Springboot和mybatis进行延迟加载时候报出如下的错误: org.apache.ibatis.executor.loader.javassist.JavassistProxyFact ...

  8. OkHttp3实现Cookies管理及持久化

    转发自:http://www.codeceo.com/article/okhttp3-cookies-manage.html OKHttp3正式版刚发布了没几天,正好重构之前的代码,于是第一时间入坑了 ...

  9. QMYSQL driver not loaded

    QT5 连接 QMYSQL 数据库时出现错误:QMYSQL driver not loaded. 解决方法如图:(图中使用指令:ldd libqsqlmysql.so) 从结果图显示中:libmysq ...

  10. Android之ListView的使用技巧

    之前有总结过关于ListView的一些优化技巧,比如它的ConvertView的复用Recycler机制,使用ViewHolder来提高列表条目的findById的效率,以及宽高的设置确定值的好处,如 ...