Java设计模式——享元模式
2016-04-25 13:35
501 查看
概述
在有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。版权说明
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
本文作者:Coding-Naga
发表日期: 2016年4月25日
本文链接:http://blog.csdn.net/lemon_tree12138/article/details/51241598
来源:CSDN
更多内容:分类 >> 设计模式
目录
概述版权说明
目录
享元模式
定义
单纯享元模式
不共享的享元模式
复合享元模式
JDK 里的享元模式
Ref
GitHub 源码下载
享元模式
定义
享元模式是一种结构型模式,运用共享技术有效地支持大量细粒度的对象。单纯享元模式
在享元模式中,就其定义我们可以构建出单纯的享元模式。下图是单纯享元模式的类图:在单纯的享元模式中,需要给出一个抽象接口,以规定出所有具体享元角色需要实现的方法。实现如下:
Flyweight.java
public interface Flyweight { public void operation(String state); }
对于享元部分,ConcreteFlyweight 必须是可共享的,它保存的任何状态都必须是内部(intrinsic),ConcreteFlyweight 必须和它的应用环境场合无关。比如字符串 “Hello” 就无需关心使用它的场合,它是一个不可变的对象。
ConcreteFlyweight.java
public class ConcreteFlyweight implements Flyweight { private String intrinsicState = null; /** * 构造函数 内蕴状态作为参数传入 */ public ConcreteFlyweight(String _intrinsicState) { this.intrinsicState = _intrinsicState; } /** * 外蕴状态作为参数传入方法中 改变方法的行为 但是并不改变对象的内蕴状态 */ @Override public void operation(String extrinsicState) { System.out.println("内蕴状态:" + intrinsicState); System.out.println("外蕴状态:" + extrinsicState); } }
在享元模式中,有一个至关重要的模块就是工厂模块了。在 Flyweight Factory 里维护了一个 Flyweight 池(存放内部状态),Flyweight Factory 就是通过这个 Flyweight 池对整个享元模式进行控制。
FlyweightFactory.java
public class FlyweightFactory { private Map<Integer, Flyweight> labels = new HashMap<Integer, Flyweight>(); public Flyweight factory(String intrinsicState) { int hashCode = intrinsicState.hashCode(); Flyweight fly = labels.get(hashCode); if (fly == null) { fly = new ConcreteFlyweight(intrinsicState); labels.put(hashCode, fly); } return fly; } }
在上面的工厂模块中可以看到,FlyweightFactory 实际上是起到了一个过滤筛选的功能,过滤重复的对象,缓存新对象。
不共享的享元模式
与共享的享元对象相对的就是不共享的享元对象。关于不共享的享元对象,可能你会有一些疑问,既然不共享,为何还要包含到享元模式中来呢?这可能是出于完整性的考虑,或是要某些场景下既要使用共享的享元,又要使用不共享的享元吧。关于这一点本人也还没有完全理解,也有可能根本不需要这一个不共享的享元对象吧。下面是不共享的享元类图:不共享的享元实现与 ConcreteFlyweight 无异。如下:
UnsharedConcreteFlyweight.java
public class UnsharedConcreteFlyweight implements Flyweight { private String intrinsicState = null; public UnsharedConcreteFlyweight(String _intrinsicState) { this.intrinsicState = _intrinsicState; } @Override public void operation(String extrinsicState) { System.out.println("内蕴状态:" + intrinsicState); System.out.println("外蕴状态:" + extrinsicState); } }
下面是对单纯的享元与不共享的享元进行测试的代码。
Client.java
public class Client { public static void main(String[] args) { FlyweightFactory factory = new FlyweightFactory(); Flyweight fly1 = factory.factory("Hello"); fly1.operation("ExtrinsicState-1"); Flyweight fly2 = factory.factory("DesignPattern"); fly2.operation("ExtrinsicState-2"); Flyweight fly3 = factory.factory("Flyweight"); fly3.operation("ExtrinsicState-3"); Flyweight fly4 = factory.factory("Hello"); fly4.operation("ExtrinsicState-4"); System.out.println("fly1 == fly2 ? " + (fly1 == fly2)); System.out.println("fly1 == fly3 ? " + (fly1 == fly3)); System.out.println("fly1 == fly4 ? " + (fly1 == fly4)); Flyweight fly5 = new UnsharedConcreteFlyweight("Unshared"); fly5.operation("ExtrinsicState-5"); } }
内蕴状态:Hello 外蕴状态:ExtrinsicState-1 内蕴状态:DesignPattern 外蕴状态:ExtrinsicState-2 内蕴状态:Flyweight 外蕴状态:ExtrinsicState-3 内蕴状态:Hello 外蕴状态:ExtrinsicState-4 fly1 == fly2 ? false fly1 == fly3 ? false fly1 == fly4 ? true 内蕴状态:Unshared 外蕴状态:ExtrinsicState-5
复合享元模式
在上面的单纯享元中,所有的享元可以说是在同一个分组里。有时候这样的大集合可能并不能发挥出很好的应用功能,所以引入了复合式的享元模式。下面是复合式享元模式类图:复合式享元相当于多个单纯享元的集合。也就是说复合享元相当于对单纯享元进行了一个再分组,在复合享元的每个分组里又是一个独立的单纯享元模式。相关关键代码如下:
ConcreteCompositeFlyweight.java
public class ConcreteCompositeFlyweight implements Flyweight { private Map<Integer, Flyweight> labels = new HashMap<Integer, Flyweight>(); public void add(int key, Flyweight flyweight) { labels.put(key, flyweight); } @Override public void operation(String extrinsicState) { Flyweight flyweight = null; for (Object key : labels.keySet()) { flyweight = labels.get(key); flyweight.operation(extrinsicState); } } }
对于其构建工厂也需要进行重新设计,如下:
FlyweightFactory.java
public class FlyweightFactory { private Map<Integer, Flyweight> labels = new HashMap<Integer, Flyweight>(); /** * 单纯享元工厂 */ public Flyweight factory(String intrinsicState) { ... ... return fly; } /** * 复合享元工厂 */ public Flyweight compositeFactory(List<String> intrinsicStates) { ConcreteCompositeFlyweight flyweight = new ConcreteCompositeFlyweight(); for (String intrinsicState : intrinsicStates) { flyweight.add(intrinsicState.hashCode(), factory(intrinsicState)); } return flyweight; } }
测试类
Client.java
public void compositeFlyweight() { List<String> intrinsicStates = new ArrayList<String>(); intrinsicStates.add("Hello"); intrinsicStates.add("Java"); intrinsicStates.add("DesignPattern"); intrinsicStates.add("Flyweight"); FlyweightFactory factory = new FlyweightFactory(); Flyweight flyweight1 = factory.compositeFactory(intrinsicStates); Flyweight flyweight2 = factory.compositeFactory(intrinsicStates); System.out.println("flyweight1 == flyweight2 ? " + (flyweight1 == flyweight2)); flyweight1.operation("复合享元-1"); flyweight2.operation("复合享元-2"); }
flyweight1 == flyweight2 ? false 内蕴状态:Java 外蕴状态:复合享元-1 内蕴状态:Flyweight 外蕴状态:复合享元-1 内蕴状态:Hello 外蕴状态:复合享元-1 内蕴状态:DesignPattern 外蕴状态:复合享元-1 内蕴状态:Java 外蕴状态:复合享元-2 内蕴状态:Flyweight 外蕴状态:复合享元-2 内蕴状态:Hello 外蕴状态:复合享元-2 内蕴状态:DesignPattern 外蕴状态:复合享元-2
JDK 里的享元模式
在 JDK 的设计里,也有很享元模式。比如一些常量池的设计(String 常量池、Integer 常量池等等);Ref
《23 种 Java 设计模式》http://www.runoob.com/design-pattern/flyweight-pattern.html
http://www.cnblogs.com/java-my-life/archive/2012/04/26/2468499.html
GitHub 源码下载
https://github.com/William-Hai/DesignPatternCollections相关文章推荐
- PropertyChangeListener简单理解
- 什么是设计模式
- 设计模式之创建型模式 - 特别的变量问题
- 七、设计模式——装饰模式
- 设计模式总结
- 设计模式之创建型模式
- 浅谈设计模式的学习
- Ruby设计模式编程之适配器模式实战攻略
- 实例讲解Ruby使用设计模式中的装饰器模式的方法
- 设计模式中的模板方法模式在Ruby中的应用实例两则
- Ruby设计模式编程中对外观模式的应用实例分析
- 实例解析Ruby设计模式编程中Strategy策略模式的使用
- Ruby中使用设计模式中的简单工厂模式和工厂方法模式
- Ruby使用设计模式中的代理模式与装饰模式的代码实例
- 详解组合模式的结构及其在Ruby设计模式编程中的运用
- C#编程中使用设计模式中的原型模式的实例讲解
- 使用设计模式中的工厂方法模式进行C#编程的示例讲解
- 实例解析C#设计模式编程中简单工厂模式的使用
- 详解C#设计模式编程中生成器模式的使用
- 深入解析C#设计模式编程中对建造者模式的运用