博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《JAVA与模式》之享元模式
阅读量:5934 次
发布时间:2019-06-19

本文共 4813 字,大约阅读时间需要 16 分钟。

享元的定义:

享元模式英文称为“Flyweight Pattern”,如果翻译成为羽量级模式,估计会让人有点捉摸不透,而享元,则可以较好的体现该模式的用途,共享元素

享元的用途:

我们知道,在java应用中,会出现许多String a="123",String b="123"之类的String类型的变量,如果只是小应用,到还好,假设是一个庞大的系统,

有好多处都需要用定义String a="223",那开销可想而知,而JDK的开发者自然想到了这点,采用了享元模式解决创建大量相同String变量带来的

开销问题

1 String s1 = "a";2 String s2 = "a";3 System.out.println(s1 == s2);// String 也是采用享元模式 存储在常量池

执行结果:true

到此,我们先简单总结下何种情况下可以考虑使用享元模式

1、一个系统中存在着大量的细粒度对象;

2、这些细粒度对象耗费了大量的内存。 
3、这些细粒度对象的状态中的大部分都可以外部化


1 // 接口 2 interface FlyWeight { 3     public void operation(String s); 4 } 5  6 // 具体实现类 7 class ConcreteFlyWeight implements FlyWeight { 8     private String str;// 内蕴状态 9 10     public ConcreteFlyWeight(String str) {11 12         this.str = str;13     }14 15     public void operation(String s) {16         System.out.println("内蕴变量:" + str);17         System.out.println("外蕴变量:" + s);18     }19 }20 21 // 享元工厂22 class FlyWeightFactory {23     public FlyWeightFactory() {24     }25 26     private Hashtable
flyWeights = new Hashtable
();27 28 public ConcreteFlyWeight factory(String str) {29 30 ConcreteFlyWeight flyWeight;31 32 flyWeight = flyWeights.get(str);33 34 if (null == flyWeight) {35 flyWeight = new ConcreteFlyWeight(str);36 flyWeights.put(str, flyWeight);37 38 }39 return flyWeight;40 }41 42 public int getFlyWeightSize() {43 44 return flyWeights.size();45 }46 }

执行代码

1 FlyWeightFactory factory = new FlyWeightFactory();2 FlyWeight flyWeight = factory.factory("a");3 FlyWeight flyWeight2 = factory.factory("b");4 FlyWeight flyWeight3 = factory.factory("a");5 flyWeight.operation("a fly weight");6 flyWeight2.operation("b fly weight");7 flyWeight3.operation("c fly weight");8 System.out.println(flyWeight == flyWeight3);9 System.out.println(factory.getFlyWeightSize());

执行结果

内蕴变量:a

外蕴变量:a fly weight
内蕴变量:b
外蕴变量:b fly weight
内蕴变量:a
外蕴变量:c fly weight
true
2

结论:本例子享元模式中,享元工厂只有2个对象,外部可以共享他们,并且内蕴变量不会受到影响

整理下模式框架代码

     ●  抽象享元(Flyweight)角色 :给出一个抽象接口,以规定出所有具体享元角色需要实现的方法。

  ●  具体享元(ConcreteFlyweight)角色:实现抽象享元角色所规定出的接口。如果有内蕴状态的话,必须负责为内蕴状态提供存储空间。

  ●  享元工厂(FlyweightFactory)角色 :本角色负责创建和管理享元角色。本角色必须保证享元对象可以被系统适当地共享。当一个客户端对象调用一个享元对象的时候,享元工厂角色会检查系统中是否已经有一个符合要求的享元对象。如果已经有了,享元工厂角色就应当提供这个已有的享元对象;如果系统中没有一个适当的享元对象的话,享元工厂角色就应当创建一个合适的享元对象。

 

我们会发现,享元模式其实是简单工厂的包装,当然实际场景是不一样的


 复合享元模式

上述说的其实是单纯的享元,享元模式还有一种复杂的情况,就是复合享元。

在单纯享元模式中,所有的享元对象都是单纯享元对象,也就是说都是可以直接共享的

将一些单纯享元使用合成模式加以复合,形成复合享元对象。这样的复合享元对象本身不能共享,但是它们可以分解成单纯享元对象,而后者则可以共享。

我们看下个例子

1 CompositeFlyWeigthFactory factory2=new CompositeFlyWeigthFactory(); 2         List
ls=Arrays.asList(new String[]{"a","b","c","a","d"}); 3 FlyWeight compositeFly=factory2.factory(ls); 4 FlyWeight compositeFly2=factory2.factory(ls); 5 System.out.println("---------------compositeFly-----------------"); 6 compositeFly.operation("a composite fly weight"); 7 System.out.println("---------------compositeFly2-----------------"); 8 compositeFly2.operation("a composite fly weight"); 9 10 System.out.println(compositeFly==compositeFly2);11 System.out.println(factory2.factory("a")==factory2.factory("a"));

执行结果:

内蕴变量:d

外蕴变量:a composite fly weight
内蕴变量:a
外蕴变量:a composite fly weight
内蕴变量:c
外蕴变量:a composite fly weight
内蕴变量:b
外蕴变量:a composite fly weight
false
true


 

整理下,会发现复合享元模式,发现是跟组合模式类似。与单纯享元模式比较,提供了一个add方法,用来组合多个单纯享元对象

整理下模式框架代码

      ●  抽象享元(Flyweight)角色 :给出一个抽象接口,以规定出所有具体享元角色需要实现的方法。

  ●  具体享元(ConcreteFlyweight)角色:实现抽象享元角色所规定出的接口。如果有内蕴状态的话,必须负责为内蕴状态提供存储空间。

  ●   复合享元(ConcreteCompositeFlyweight)角色 :复合享元角色所代表的对象是不可以共享的,但是一个复合享元对象可以分解成为多个本身是单纯享元对象的组合。复合享元角色又称作不可共享的享元对象。

  ●   享元工厂(FlyweightFactory)角色 :本角 色负责创建和管理享元角色。本角色必须保证享元对象可以被系统适当地共享。当一个客户端对象调用一个享元对象的时候,享元工厂角色会检查系统中是否已经有 一个符合要求的享元对象。如果已经有了,享元工厂角色就应当提供这个已有的享元对象;如果系统中没有一个适当的享元对象的话,享元工厂角色就应当创建一个 合适的享元对象。


 

我们模拟一个情景,饭店的菜单只有一份,而每个顾客点的菜单却各不相同,但是肯定会有重复,我们用上述的享元模式尝试模拟下代码情景

1 //饭店菜谱工厂 2         CompositeFlyWeigthFactory orderFactory=new CompositeFlyWeigthFactory(); 3         //菜单列表 4         List
menuList=Arrays.asList(new String[]{"福跳墙","荔枝肉","锅边糊","油条","麻花"}); 5 FlyWeight c1 =orderFactory.factory(menuList.subList(0, 2));//顾客1 6 FlyWeight c2=orderFactory.factory(menuList.subList(1, 3));//顾客2 7 System.out.println("---------------c1-----------------"); 8 c1.operation("c1的菜单谱"); 9 System.out.println("---------------c2-----------------");10 c2.operation("c2的菜单普");

执行结果

---------------c1-----------------

内蕴变量:荔枝肉
外蕴变量:c1的菜单谱
内蕴变量:福跳墙
外蕴变量:c1的菜单谱
---------------c2-----------------
内蕴变量:锅边糊
外蕴变量:c2的菜单普
内蕴变量:荔枝肉
外蕴变量:c2的菜单普


 

参考:

http://blog.csdn.net/ai92/article/details/224598 

http://blog.csdn.net/jason0539/article/details/22908915

http://www.cnblogs.com/java-my-life/archive/2012/04/26/2468499.html#2937200

 

 

 

 

你可能感兴趣的文章
系统启动之后将/var/log挂载到独立的分区
查看>>
Linux 系统下各文件目录的含义
查看>>
如何导入批量的用户账号?
查看>>
System Center Operation Manager 2012(四) 安装额外MS
查看>>
Mysql For Windows安装图解
查看>>
Shader物体渲染前置效果(即:不被前面物体遮挡)
查看>>
2016年 CSS 库、框架和工具新生榜 TOP 50
查看>>
Linux帐号管理
查看>>
手把手教你搭建LyncServer2013之安装持久聊天服务器(十三)
查看>>
js中,全局变量与直接添加在window属性的区别
查看>>
人工智能与智能系统中的先驱人物
查看>>
动态ARP表项建立条件
查看>>
iOS scrollView 手动布局不能从顶部显示解决方法 oc or swift都是这个道理
查看>>
Scrapy items的介绍与使用
查看>>
React Native Android Gradle 编译流程浅析(一)
查看>>
陈松松:如何保证做出有价值的视频,让用户喜欢观看
查看>>
博为峰Java技术文章 ——JavaSE Swing使用数组和Vector创建下拉列表框
查看>>
linux rsync同步命令
查看>>
对apache中并发控制参数prefork理解和调优
查看>>
MP114配合微软UC简单DEMO
查看>>