博文地址

我的GitHub 我的博客 我的微信 我的邮箱
baiqiantao baiqiantao bqt20094 baiqiantao@sina.com

享元模式

简介

在JAVA语言中,String类型就是使用了享元模式,JAVA中的字符串常量都是存在常量池中的,JAVA会确保一个字符串常量在常量池中只有一个拷贝,避免了在创建N多相同对象时所产生的不必要的大量的资源消耗。

String string1 = "abc";
String string2 = "abc";
String string3 = new String("abc");
String string4 = new String("abc");
System.out.println(string1 == string2);//true
System.out.println(string3 == string4 || string3 == string1 || string4 == string1);//false

享元模式是对象的结构模式,享元模式以共享的方式高效地支持大量的细粒度对象。

Flyweight在拳击比赛中指最轻量级拳击选手,即“蝇量级”,这里选择使用“享元模式”的意译,是因为这样更能反映模式的用意。

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

享元对象能做到共享的关键是区分内蕴状态Internal State和外蕴状态External State。

  • 一个内蕴状态是存储在享元对象内部的,并且是不会随环境的改变而有所不同。因此,一个享元可以具有内蕴状态并可以共享。
  • 一个外蕴状态是随环境的改变而改变的、不可以共享的。享元对象的外蕴状态必须由客户端保存,并在享元对象被创建之后,在需要使用的时候再传入到享元对象内部。
  • 外蕴状态不可以影响享元对象的内蕴状态,它们是相互独立的。

享元模式所涉及到的角色如下:

  • 抽象享元(Flyweight)角色 :给出一个抽象接口,以规定出所有具体享元角色需要实现的方法。
  • 具体享元(ConcreteFlyweight)角色:实现抽象享元角色所规定出的接口。如果有内蕴状态的话,必须负责为内蕴状态提供存储空间。
  • 享元工厂(FlyweightFactory)角色 :负责创建和管理享元角色。本角色必须保证享元对象可以被系统适当地共享。当一个客户端对象调用一个享元对象的时候,享元工厂角色会检查系统中是否已经有一个符合要求的享元对象,如果已经有了,享元工厂角色就应当提供这个已有的享元对象;如果系统中没有一个适当的享元对象的话,享元工厂角色就应当创建一个合适的享元对象。

享元模式的优点在于它大幅度地降低内存中对象的数量,但是,它做到这一点所付出的代价也是很高的:

  • 享元模式使得系统更加复杂。为了使对象可以共享,需要将一些状态外部化,这使得程序的逻辑复杂化
  • 享元模式将享元对象的状态外部化,而读取外部状态使得运行时间稍微变长

作用:共享对象,节省内存 
优点:享元模式可以降低内存中的对象数量,提高性能 
缺点:需要将一些状态外部化,程序逻辑将变得复杂,且在读取外部状态时耗时增加

案例

抽象享元类

public interface IFlyweight {
action(int arg);//参数是外蕴状态,通过这个接口,享元类可以接受并作用于外部状态
}

具体享元类

public class ConcreteFlyweight implements IFlyweight {
private String intrinsicState = null;//有一个内蕴状态,内蕴状态在对象创建之后,就不能再改变了
public ConcreteFlyweight(String intrinsicState) {
this.intrinsicState = intrinsicState; //一般在构造享元对象时通过参数确定内蕴状态
} @Override
public void action(int arg) { //外蕴状态作为参数传入方法中,可以改变方法的行为,但并不改变对象的内蕴状态
System.out.println("参数值: " + arg + " intrinsicState = " + this.intrinsicState);
}
}

享元工厂类 
客户端不可以直接构造享元类对象,只能由享元工厂创建并管理,在一个项目中只会存在一个享元工厂,因此用单例来获取,而享元对象则通过工厂获取,有则取用,无则创建

public class FlyweightFactory {
private Map<String, IFlyweight> flyweights = new HashMap<>();//存储已创建的对象 public IFlyweight getFlyweight(String arg) {
IFlyweight flyweight = flyweights.get(arg); //先从系统中取,如果存在直接使用,如果不存在则创建并保存起来
if (flyweight == null) {
flyweight = new ConcreteFlyweight(arg);
flyweights.put(arg, flyweight);
}
return flyweight;
} //以下是标准的单例模式写法
private FlyweightFactory() {
} public static FlyweightFactory getInstance() {
return SingleHolder.INSTANCE;
} private static class SingleHolder {
private static final FlyweightFactory INSTANCE = new FlyweightFactory();
}
}

2016-03-17

Flyweight 享元模式 MD的更多相关文章

  1. C++设计模式-Flyweight享元模式

    Flyweight享元模式 作用:运用共享技术有效地支持大量细粒度的对象. 内部状态intrinsic和外部状态extrinsic: 1)Flyweight模式中,最重要的是将对象分解成intrins ...

  2. Flyweight享元模式(结构型模式)

    1.面向对象的缺点 虽然OOP能很好的解决系统抽象的问题,并且在大多数的情况下,也不会损失系统的性能.但是在某些特殊的业务下,由于对象的数量太多,采用面向对象会给系统带来难以承受的内存开销.示例代码如 ...

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

    运用共享技术支持大量细粒度对象的使用 Flyweight模式(享元) Java深入到一定程度,就不可避免的碰到设计模式这一概念,了解设计模式,将使自己对java中的接口或抽象类应用有更深的理解.设计模 ...

  4. 设计模式11: Flyweight 享元模式(结构型模式)

    Flyweight 享元模式(结构型模式) 面向对象的代价 面向对象很好的解决了系统抽象性的问题,同时在大多数情况下也不会损及系统的性能.但是,在某些特殊应用中,由于对象的数量太大,采用面向对象会给系 ...

  5. 20、FlyWeight 享元模式

    池化的思想 1.Flyweight享元模式 运用共享技术有效地支持大量细粒度对象的复用.系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用.由于享元模式要求能够共享的对象必 ...

  6. Flyweight(享元模式)

    import java.util.Hashtable; /** * 享元模式 * @author TMAC-J * 享元模式一般和工厂模式一起使用,但此处为了更好说明,只用享元模式 * 定义:享元模式 ...

  7. 设计模式(十二): Flyweight享元模式 -- 结构型模式

    说明: 相对于其它模式,Flyweight模式在PHP实现似乎没有太大的意义,因为PHP的生命周期就在一个请求,请求执行完了,php占用的资源都被释放.我们只是为了学习而简单做了介绍. 1. 概述 面 ...

  8. 二十、Flyweight 享元模式

    原理: 代码清单: BigChar public class BigChar { //字符名称 private char charname; //大型字符 # . \n 组成 private Stri ...

  9. 设计模式(11)--Flyweight(享元模式)--结构型

    作者QQ:1095737364    QQ群:123300273     欢迎加入! 1.模式定义: 享元模式是对象的结构模式.享元模式以共享的方式高效地支持大量的细粒度对象. 2.模式特点: 享元模 ...

随机推荐

  1. 线上zk节点报org.apache.zookeeper.server.NIOServerCnxnFactory.run(NIOServerCnxnFactory.java:187) at java.lang.Thread.run(libgcj.so.10)

    线上zk做配置管理,最近突然发现两个节点一直在刷下边 java.nio.channels.CancelledKeyException    at gnu.java.nio.SelectionKeyIm ...

  2. 一个线上程序bug,由通用补数程序引起

    下游发现接口可用率非100%,马上线上查看,发现数据在有些情况下通用补数的数据是空, 有20%的用户是没有相应偏好等的数据的,需要通用补数来补数,结果通用补数没有数据. 通用补数数据的检查报警时必须要 ...

  3. luogu P2757 [国家集训队]等差子序列

    题目链接 luogu P2757 [国家集训队]等差子序列 题解 线段树好题 我选择暴力 代码 // luogu-judger-enable-o2 #include<cstdio> inl ...

  4. HDU 5810 Balls and Boxes 数学

    Balls and Boxes 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5810 Description Mr. Chopsticks is i ...

  5. 使用 IntraWeb (7) - 主模板

    TIWLayoutMgrHTML.TIWTemplateProcessorHTML 属于页面级的模板, 如果要全站统一模板, 当然要用主模板. TIWTemplateProcessorHTML 通过其 ...

  6. Programming 2D Games 读书笔记(第五章)

      http://www.programming2dgames.com/chapter5.htm 示例一:Planet 真正示例的开始,首先是载入2张图片 1.Graphics添加了2个方法 load ...

  7. systemtap 脚本示例

    .[root@localhost ~]# stap -v -e 'probe vfs.read {printf("read performed\n"); exit()}' Pass ...

  8. 使用React改版网站

    网站是毕业设计的作品,开发这个网站的目的主要用于记录一些笔记,以及聚合一些资讯信息,也算自己在网络世界中的一块静地吧,可以在这里一些技术上想法的实践. 网站最初前端使用vue开发,在前段时间由于项目的 ...

  9. Chrome 开发者工具中的命令菜单

    单 大家对命令菜单(Command Menu)应该都不陌生.目前主流的编辑器中都内置了对该功能的支持.在 Sublime Text 和 Visual Studio Code 中你都可以通过快捷键 Ct ...

  10. 【多线程】java多线程实现生产者消费者模式

    思考问题: 1.为什么用wait()+notify()实现生产者消费者模式? wait()方法可以暂停线程,并释放对象锁 notify()方法可以唤醒需要该对象锁的其他线程,并在执行完后续步骤,到了s ...