Flyweight 享元模式 MD
| 我的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的更多相关文章
- C++设计模式-Flyweight享元模式
Flyweight享元模式 作用:运用共享技术有效地支持大量细粒度的对象. 内部状态intrinsic和外部状态extrinsic: 1)Flyweight模式中,最重要的是将对象分解成intrins ...
- Flyweight享元模式(结构型模式)
1.面向对象的缺点 虽然OOP能很好的解决系统抽象的问题,并且在大多数的情况下,也不会损失系统的性能.但是在某些特殊的业务下,由于对象的数量太多,采用面向对象会给系统带来难以承受的内存开销.示例代码如 ...
- 设计模式之flyweight享元模式
运用共享技术支持大量细粒度对象的使用 Flyweight模式(享元) Java深入到一定程度,就不可避免的碰到设计模式这一概念,了解设计模式,将使自己对java中的接口或抽象类应用有更深的理解.设计模 ...
- 设计模式11: Flyweight 享元模式(结构型模式)
Flyweight 享元模式(结构型模式) 面向对象的代价 面向对象很好的解决了系统抽象性的问题,同时在大多数情况下也不会损及系统的性能.但是,在某些特殊应用中,由于对象的数量太大,采用面向对象会给系 ...
- 20、FlyWeight 享元模式
池化的思想 1.Flyweight享元模式 运用共享技术有效地支持大量细粒度对象的复用.系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用.由于享元模式要求能够共享的对象必 ...
- Flyweight(享元模式)
import java.util.Hashtable; /** * 享元模式 * @author TMAC-J * 享元模式一般和工厂模式一起使用,但此处为了更好说明,只用享元模式 * 定义:享元模式 ...
- 设计模式(十二): Flyweight享元模式 -- 结构型模式
说明: 相对于其它模式,Flyweight模式在PHP实现似乎没有太大的意义,因为PHP的生命周期就在一个请求,请求执行完了,php占用的资源都被释放.我们只是为了学习而简单做了介绍. 1. 概述 面 ...
- 二十、Flyweight 享元模式
原理: 代码清单: BigChar public class BigChar { //字符名称 private char charname; //大型字符 # . \n 组成 private Stri ...
- 设计模式(11)--Flyweight(享元模式)--结构型
作者QQ:1095737364 QQ群:123300273 欢迎加入! 1.模式定义: 享元模式是对象的结构模式.享元模式以共享的方式高效地支持大量的细粒度对象. 2.模式特点: 享元模 ...
随机推荐
- [HDU2874]Connections between cities
思路:LCA裸题.本来是帮pechpo调错,结果自己写了半天… 设$dis_x$是点$x$到根结点距离,不难想到两点$u$.$v$之间最短距离等于$dis_u+dis_v-dis_{LCA(u,v)} ...
- BZOJ2468 : [中山市选2010]三核苷酸
令d[i]为第i个样本数据,cnt为样本个数,经过化简可得 \[ans=\frac{\sum(d[i]^2)}{cnt}-(\frac{\sum d[i]}{cnt})^2\] 枚举每一种可能的三核苷 ...
- Redis使用小结
Redis官方没有windows版本的,对于Windows环境的redis,有如下两个方案 微软的移植版本,但只支持到3.2 下载地址 win10及以上的版本直接通过win10的liunx子系统执行 ...
- HDU 4821 String(2013长春现场赛I题)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4821 字符串题. 现场使用字符串HASH乱搞的. 枚举开头! #include <stdio.h ...
- The STM32F746G-DISCO discovery board -- MBED
https://developer.mbed.org/platforms/ST-Discovery-F746NG/ Microcontroller features STM32F46NGH6 in T ...
- [置顶] Android系统移植与调试之------->build.prop文件详细赏析
小知识:什么是build.prop? /system/build.prop 是一个属性文件,在Android系统中.prop文件很重要,记录了系统的设置和改变,类似於/etc中的文件.这个文件是如 ...
- socket recv阻塞与非阻塞error总结
recv是socket编程中最常用的函数之一,在阻塞状态的recv有时候会返回不同的值,而对于错误值也有相应的错误码,分别对应不同的状态,下面是我针对常见的几种网络状态的简单总结. 首先阻塞接收的re ...
- [Android 动画]简要分析一下Animator 与 Animation
大家假设喜欢我的博客,请关注一下我的微博,请点击这里(http://weibo.com/kifile),谢谢 转载请标明出处(http://blog.csdn.net/kifile),再次感谢 在 A ...
- CSDN学院升级公告
CSDN学院将于2015年8月5日凌晨00:00-10:00进行停站升级,升级期间会影响大家的正常訪问和操作.给各位用户带来的不便敬请谅解. 升级结束后有不论什么问题请发邮件到webmaster@cs ...
- 为什么使用this构造器
当一个类有多个构造函数的时候,常使用this构造器: public class SomeClass { public SomeClass() { //TODO:初始化一些字段 } public Som ...