PS一句:最终还是选择CSDN来整理发表这几年的知识点,该文章平行迁移到CSDN。因为CSDN也支持MarkDown语法了,牛逼啊!

【工匠若水 http://blog.csdn.net/yanbober】 阅读前一篇《设计模式(结构型)之外观模式(Facade Pattern)》http://blog.csdn.net/yanbober/article/details/45476527

概述

当一个软件系统在运行时产生的对象数量太多,将导致运行代价过高,带来系统性能下降等问题。所以需要采用一个共享来避免大量拥有相同内容对象的开销。在Java中,String类型就是使用了享元模式。String对象是final类型,对象一旦创建就不可改变。在Java中字符串常量都是存在常量池中的,Java会确保一个字符串常量在常量池中只有一个拷贝。

核心

概念: 运用共享技术有效地支持大量细粒度对象的复用。系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用。由于享元模式要求能够共享的对象必须是细粒度对象,因此它又称为轻量级模式,它是一种对象结构型模式。

关于享元基础:

享元对象共享的关键是区分了内部状态(Intrinsic State)和外部状态(Extrinsic State)。

内部状态

存储在享元对象内部并且不会随环境改变而改变的状态,内部状态可以共享。

外部状态

享元对象的外部状态通常由客户端保存,并在享元对象被创建之后,需要使用的时候再传入到享元对象内部。随环境改变而改变的、不可以共享的状态。一个外部状态与另一个外部状态之间是相互独立的。

由于区分了内部状态和外部状态,我们可以将具有相同内部状态的对象存储在享元池中,享元池中的对象是可以实现共享的,需要的时候就将对象从享元池中取出,实现对象的复用。通过向取出的对象注入不同的外部状态,可以得到一系列相似的对象,而这些对象在内存中实际上只存储一份。

享元模式分类:

  • 单纯享元模式
  • 复合享元模式

单纯享元模式结构重要核心模块:

抽象享元角色

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

具体享元角色

实现抽象角色规定的方法。如果存在内部状态,就负责为内部状态提供存储空间。

享元工厂角色

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

客户端角色

维护对所有享元对象的引用,而且还需要存储对应的外部状态。

单纯享元模式和创建型的简单工厂模式实现上非常相似,但是它的重点或者用意却和工厂模式截然不同。工厂模式的使用主要是为了使系统不依赖于实现得细节;而在享元模式的主要目的是避免大量拥有相同内容对象的开销。

复合享元模式结构重要核心模块:

抽象享元角色

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

具体享元角色

实现抽象角色规定的方法。如果存在内部状态,就负责为内部状态提供存储空间。

复合享元角色

它所代表的对象是不可以共享的,并且可以分解成为多个单纯享元对象的组合。

享元工厂角色

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

客户端角色

维护对所有享元对象的引用,而且还需要存储对应的外部状态。

使用场景

一个系统有大量相同或者相似的对象,造成内存的大量耗费。

对象的大部分状态都可以外部化,可以将这些外部状态传入对象中。

在使用享元模式时需要维护一个存储享元对象的享元池,而这需要耗费一定的系统资源,因此,应当在需要多次重复使用享元对象时才值得使用享元模式。

程序猿实例

单纯享元模式实例:例子完全就是核心点的文字翻译代码,不做过多解释。

package yanbober.github.io;import java.util.HashMap;
import java.util.Map;//抽象享元角色类
interface ICustomerString {//外部状态以参数的形式通过此方法传入void opt(String state);
}
//具体享元角色类
class CustomerStringImpl implements ICustomerString {//负责为内部状态提供存储空间private Character mInnerState = null;public CustomerStringImpl(Character mInnerState) {this.mInnerState = mInnerState;}@Overridepublic void opt(String state) {System.out.println("Inner state = "+this.mInnerState);System.out.println("Out state = "+state);}
}
//享元工厂角色类
//一般而言,享元工厂对象在整个系统中只有一个,因此也可以使用单例模式
class CustomerStringFactory {private Map<Character, ICustomerString> map = new HashMap<>();public ICustomerString factory(Character state) {ICustomerString cacheTemp = map.get(state);if (cacheTemp == null) {cacheTemp = new CustomerStringImpl(state);map.put(state, cacheTemp);}return cacheTemp;}
}
//客户端
public class Main {public static void main(String[] args) {CustomerStringFactory factory = new CustomerStringFactory();ICustomerString customerString = factory.factory(new Character('Y'));customerString.opt("YanBo");customerString = factory.factory(new Character('B'));customerString.opt("Bob");customerString = factory.factory(new Character('Y'));customerString.opt("Jesse");}
}

运行结果:
Inner state = Y
Out state = YanBo
Inner state = B
Out state = Bob
Inner state = Y
Out state = Jesse

上边示例结果一目了然可以看出来简单享元模式的特点。

复合享元模式实例:

如下例子就是一个复合享元模式,添加了复合对象,具体如下:

package yanbober.github.io;import java.util.*;//抽象享元角色类
interface ICustomerString {//外部状态以参数的形式通过此方法传入void opt(String state);
}
//具体享元角色类
class CustomerStringImpl implements ICustomerString {//负责为内部状态提供存储空间private Character mInnerState = null;public CustomerStringImpl(Character mInnerState) {this.mInnerState = mInnerState;}@Overridepublic void opt(String state) {System.out.println("Inner state = "+this.mInnerState);System.out.println("Out state = "+state);}
}
//复合享元对象
class MultipleCustomerStringImpl implements ICustomerString {private Map<Character, ICustomerString> map = new HashMap<>();public void add(Character key, ICustomerString value) {map.put(key, value);}@Overridepublic void opt(String state) {ICustomerString temp;for (Character obj : map.keySet()) {temp = map.get(obj);temp.opt(state);}}
}
//享元工厂角色类
class CustomerStringFactory {//一般而言,享元工厂对象在整个系统中只有一个,因此也可以使用单例模式private Map<Character, ICustomerString> map = new HashMap<>();//上例的单纯享元模式public ICustomerString factory(Character state) {ICustomerString cacheTemp = map.get(state);if (cacheTemp == null) {cacheTemp = new CustomerStringImpl(state);map.put(state, cacheTemp);}return cacheTemp;}//复合享元模式public ICustomerString factory(List<Character> states) {MultipleCustomerStringImpl impl = new MultipleCustomerStringImpl();for (Character state : states) {impl.add(state, this.factory(state));}return impl;}
}
//客户端
public class Main {public static void main(String[] args) {List<Character> states = new ArrayList<>();states.add('Y');states.add('A');states.add('N');states.add('B');states.add('O');states.add('Y');states.add('B');CustomerStringFactory factory = new CustomerStringFactory();ICustomerString customerString1 = factory.factory(states);ICustomerString customerString2 = factory.factory(states);customerString1.opt("Mutex object test!");}
}

总结一把

从上面代码你可以发现,由于享元模式的复杂,实际应用也不是很多,这是我们更加无法看清他的真面目了。不过享元模式并不是鸡肋,它的精髓是共享,是对我们系统优化非常有好处的,而且这种思想已经别越来越多的应用,这应该就算是享元模式的应用了吧。

享元模式优点:

  • 可以极大减少内存中对象的数量,使得相同或相似对象在内存中只保存一份,从而可以节约系统资源,提高系统性能。
  • 享元模式的外部状态相对独立,而且不会影响其内部状态,从而使得享元对象可以在不同的环境中被共享。

享元模式缺点:

  • 享元模式使得系统变得复杂,需要分离出内部状态和外部状态,这使得程序的逻辑复杂化。
  • 为了使对象可以共享,享元模式需要将享元对象的部分状态外部化,而读取外部状态将使得运行时间变长。

【工匠若水 http://blog.csdn.net/yanbober】 继续阅读《设计模式(结构型)之代理模式(Proxy Pattern)》 http://blog.csdn.net/yanbober/article/details/45480965#t3

设计模式(结构型)之享元模式(Flyweight Pattern)相关推荐

  1. [设计模式] 结构型:享元模式(Flyweight Pattern)

    文章目录 什么是享元模式 设计与实现 Integer应用享元模式 什么是享元模式 "享"的意思是"共享","元"的意思是"对象&q ...

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

    设计模式(十)享元模式Flyweight(结构型) 说明: 相对于其它模式,Flyweight模式在PHP实现似乎没有太大的意义,因为PHP的生命周期就在一个请求,请求执行完了,php占用的资源都被释 ...

  3. Java设计模式之结构型:享元模式

    一.什么是享元模式: 享元模式通过共享技术有效地支持细粒度.状态变化小的对象复用,当系统中存在有多个相同的对象,那么只共享一份,不必每个都去实例化一个对象,极大地减少系统中对象的数量.比如说一个文本系 ...

  4. 【设计模式自习室】享元模式 Flyweight Pattern:减少对象数量

    前言 <设计模式自习室>系列,顾名思义,本系列文章带你温习常见的设计模式.主要内容有: 该模式的介绍,包括: 引子.意图(大白话解释) 类图.时序图(理论规范) 该模式的代码示例:熟悉该模 ...

  5. 享元模式(Flyweight Pattern)详解

    https://www.cnblogs.com/amei0/p/7930013.html 享元模式(Flyweight Pattern) 定义: 采用一个共享来避免大量拥有相同内容对象的开销.这种开销 ...

  6. Net设计模式实例之享元模式( Flyweight Pattern)

    一.享元模式简介(Brief Introduction) 享元模式(Flyweight Pattern),运用共享技术有效支持大量细粒度的对象. Use sharing to support larg ...

  7. 设计模式:享元模式(Flyweight Pattern)

    1.享元模式:也叫蝇量模式,运行共享技术有效的支持大量细粒度的对象. 2.享元模式常用于系统底层开发,解决系统的性能问题.比如数据库连接池,里面都是创建好的连接对象. 3.享元模式能够解决重复对象的内 ...

  8. 26享元模式(Flyweight Pattern)

    面向对象的代价     面向对象很好地解决了系统抽象性的问题,同时在大多数情况下,也不会损及系统的性能.但是,在 某些特殊的应用中下,由于对象的数量太大,采用面向对象会给系统带来难以承受的内存开销.比 ...

  9. 享元模式 Flyweight Pattern

    享元模式的定义为:采用一个共享来避免大量拥有相同内容对象的开销. 这种开销中最常见.直观的就是内存的损耗.享元模式以共享的方式高效地支持大量的细粒度对象. 在名字和定义中都体现了共享这个核心概念,那么 ...

最新文章

  1. php的环境怎么配置文件,php环境下所有的配置文件以及作用
  2. 使用OpenCV4实现硬件级别加速
  3. CNCF 宣布 Helm 成为基金会下一个重点孵化项目
  4. Dubbo框架设计原理
  5. 如何将 Nginx 性能提升10倍?这10个“套路”请收好!
  6. 输出 100 万字、维护 3 个GitHub 项目,技术大佬的 2019 太燃了……
  7. Ant在Java项目中的使用(一眼就看会)
  8. vue : 引入、安装 jquery 、bootstrap
  9. python 进程与线程(理论部分)
  10. LeetCode 317. 离建筑物最近的距离(逆向BFS)*
  11. java中 static变量和方法到底是存在内存什么区域?
  12. 【Hive】表生成(Table-Generating)函数
  13. python+jpype+linux出现内存溢出问题解决方案
  14. python识别文字并且提示_Python识别文字,实现看图说话|CSDN博文精选
  15. stm32f407的三重ADC同步触发模式配置
  16. APM32F030多通道ADC采样
  17. cuda的安装,及pytorch调用GPU步骤
  18. springboot整合阿里云视频点播服务Vod——实现视频上传、删除、播放
  19. Crowd Counting领域论文阅读
  20. LA 3363 String Compression(dp)

热门文章

  1. c语言逐行扫描打印图案,用逐行扫描法读取4X4键盘矩阵,不能扫描出第一列按键?...
  2. 微信小程序实战 (WXML:小程序版HTML)
  3. invalid bound statement (not found):xxxMapper.insert
  4. Unity-数学3-数学符号
  5. 硬件描述语言Verilog学习(一)
  6. 标准分幅下的图幅号转换成经纬度坐标【原理+源代码】
  7. 设计模式(二)抽象工厂模式
  8. 利用Java反射机制实现短信接口更换
  9. 赛门铁克:看***如何能够通过LED灯泡窃取你的隐私
  10. 目标检测:各种网络结构对比