23种设计模式之_享元模式
来源:互联网 发布:java生成时间戳 编辑:程序博客网 时间:2024/06/05 19:49
- 一什么是享元模式
- 二享元模式几个角色
- 抽象享元类Flyweight
- 具体享元类FlyWeightAImlFlyWeightBIml
- 享元工厂类FlyweightFactoiy
- 客户类Client
- 三享元模式使用场景
- 四代码分析
设计模式的熟练掌握,能够更容易理解系统的底层架构实现。
一、什么是享元模式
享元模式(Flyweight Pattern):以共享的方式高效的支持大量的细粒度对象。通过复用内存中已存在的对象,降低系统创建对象实例的性能消耗。
享元的英文是Flyweight,是一个来自体育方面的专业用语,在拳击、摔跤和举重比赛中特指最轻量的级别。把这个单词移植到软件工程中,也是用来表示特别小的对象,即细粒度的对象。至于为什么把Flyweight翻译为“享元”,可以理解为共享元对象,也就是共享细粒度对象。
在面向对象中,大量细粒度对象的创建、销毁及存储所造成的资源和性能上的损耗,可能会在系统运行时形成瓶颈。那么该如何避免产生大量的细粒度对象,同时又不影响系统使用面向对象的方式进行操作呢?享元模式提供了一个比较好的解决方案。
二、享元模式几个角色
uml类图:
抽象享元类(Flyweight)
它是所有具体享元类的超类。为这些类规定出需要实现的公共接口,那些需要外蕴状态(Exte的操作可以通过方法的参数传入。抽象享元的接口使得享元变得可能,但是并不强制子类实行共享,因此并非所有的享元对象都是可以共享的。
具体享元类(FlyWeightAIml,FlyWeightBIml)
具体享元类实现了抽象享元类所规定的接口。如果有内蕴状态的话,必须负责为内蕴状态提供存储空间。享元对象的内蕴状态必须与对象所处的周围环境无关,从而使得享元对象可以在系统内共享。有时候具体享元类又称为单纯具体享元类,因为复合享元类是由单纯具体享元角色通过复合而成的。
享元工厂类(FlyweightFactoiy)
享元工厂类负责创建和管理享元对象。当一个客户端对象请求一个享元对象的时候,享元工厂需要检查系统中是否已经有一个符合要求的享元对象,如果已经有了,享元工厂角色就应当提供这个已有的享元对象;如果系统中没有适当的享元对象的话,享元工厂角色就应当创建一个新的合适的享元对象。
客户类(Client)
客户类需要自行存储所有享元对象的外蕴状态。
三、享元模式使用场景
当系统中某个对象类型的实例较多的时候;
当系统设计时候,对象实例真正有区别的分类很少,例如对于拼音,如果对每个字母都初始化一个对象实例的话,这样实例就太多了。使用享元模式只需要提前初始化基本拼音,就可以任意进行组装成不同的拼音
四、代码分析
网上很多例子,看着不太明白。使用字母进行举例子通俗易懂。
CharactorFactory 工厂
package Chartflyweight;import java.util.Hashtable;public class CharactorFactory { private Hashtable<String, FlyWeight> charactors = new Hashtable<String, FlyWeight>(); // 构造函数 public CharactorFactory() { charactors.put("A", new FlyWeightAIml()); charactors.put("B", new FlyWeightBIml()); } // 获得指定字符实例 public FlyWeight getCharactor(String key) { FlyWeight charactor = (FlyWeight) charactors.get(key); if (charactor == null) { if (key.equals("A")) { charactor = new FlyWeightAIml(); } else if (key.equals("B")) { charactor = new FlyWeightBIml(); } charactors.put(key, charactor); } return charactor; }}
FlyWeight 享元抽象类
package Chartflyweight;public abstract class FlyWeight { protected String charStr = ""; protected int fontSize; protected abstract void operator(int fontSize); // 显示方法 protected abstract void displayCharator();}
FlyWeightAIml 具体实现类
package Chartflyweight;public class FlyWeightAIml extends FlyWeight { @Override protected void operator(int fontSize) { this.fontSize=fontSize; } public FlyWeightAIml() { this.charStr = "A"; this.fontSize=12; } @Override protected void displayCharator() { System.out.println("字符:" + this.charStr + ",大小:" + fontSize); }}
FlyWeightBIml 具体实现类
package Chartflyweight;public class FlyWeightBIml extends FlyWeight { @Override protected void operator(int fontSize) { this.fontSize = fontSize; } public FlyWeightBIml() { this.charStr = "B"; this.fontSize = 12; } @Override protected void displayCharator() { System.out.println("字符:" + this.charStr + ",大小:" + fontSize); }}
Client 测试类 1 ( 简单的剔除外蕴状态,在client中进行存储)
package Chartflyweight;//如何有特别多的外部状态,则需要很多的函数,函数进行抽取public class Clinet { public static void main(String[] args) { FlyWeightAIml a = new FlyWeightAIml(); FlyWeightBIml b = new FlyWeightBIml(); // 显示字符A display(a, 12); // 显示字符B display(b, 14); } // 设置字符的大小 public static void display(FlyWeight objChar, int nSize) { try { System.out.println("字符:" + objChar.charStr + ",大小:" + nSize); } catch (Exception err) { } }}
测试类2 (考虑到复用性,将外蕴状态作为参数在使用时候进行传递)
package Chartflyweight;//如何有特别多的外部状态,则需要很多的函数,函数进行抽取public class Clinet2 { public static void main(String[] args) { FlyWeightAIml a = new FlyWeightAIml(); FlyWeightBIml b = new FlyWeightBIml(); // 设置字符A的大小 a.operator(12); // 显示字符B a.displayCharator(); // 设置字符B的大小 b.operator(14); // 显示字符B b.displayCharator(); }}
输出结果:
字符:A,大小:12
字符:B,大小:14
上面代码内蕴共享对象是 A,B ,而外蕴不共享状态是 fontSize.
引用个例子:
享元模式在一般的项目开发中并不常用,而是常常应用于系统底层的开发,以便解决系统的性能问题。
Java和.Net中的String类型就是使用了享元模式。如果在Java或者.NET中已经创建了一个字符串对象s1,那么下次再创建相同的字符串s2的时候,系统只是把s2的引用指向s1所引用的具体对象,这就实现了相同字符串在内存中的共享。如果每次执行s1=“abc”操作的时候,都创建一个新的字符串对象的话,那么内存的开销会很大。
如果大家有兴趣的话,可以用下面的程序进行测试,就会知道s1和s2的引用是否一致:
Java代码:
String s1 = "测试字符串1";String s2 = "测试字符串1";//“==”用来判断两个对象是否是同一个,equals判断字符串的值是否相等if( s1 == s2 ){System.out.println("两者一致");}else{System.out.println("两者不一致");}
程序运行后,输出的结果为“两者一致”,这说明String类的设计采用了享元模式。如果s1的内容发生了变化,比如执行了s1 += “变化”的语句,那么s1与s2的引用将不再一致。
Java DEMO :http://pan.baidu.com/s/1bpKhdpl
引用:
享元(Flyweight)模式 http://www.cnblogs.com/zhenyulu/articles/55793.html
设计模式之享元模式 http://blog.csdn.net/wanghao72214/article/details/4046182
Flyweight模式的学习 http://supercrsky.iteye.com/blog/372714
- 23种设计模式之_享元模式
- 大话设计模式_享元模式
- 设计模式_享元模式
- java设计模式_享元模式
- 设计模式_享元模式
- 设计模式_享元模式(15)
- 23种设计模式(11)_结构型_享元模式(Flyweight Pattern)
- 23种设计模式之享元模式(FlyWeight)
- c++23种设计模式之享元模式
- 23种设计模式C++实例之享元模式
- 23种设计模式之享元模式
- Java设计模式_(结构型)_享元模式
- Integer注意_享元设计模式
- 设计模式之享元
- 设计模式之享元
- 设计模式 之 享元
- 设计模式之享元
- 设计模式之享元
- BZOJ 1104: [POI2007]洪水pow 并查集
- 基于tomcat的应用镜像遇到的问题
- 欢迎使用CSDN-markdown编辑器
- Java03接口与内部类
- Android画一条虚线
- 23种设计模式之_享元模式
- 设置GridView某个单元格显示的字数,其余的使用省略号显示
- C++读取BIOS信息
- 特征的转换_01-自然语言相关特征转换
- Android File类
- 找球号(一)
- 特征的转换_02-连续变量的离散化
- 关于微信小程序
- TensorFlow 1.0.0rc1上玩量化神经网络 ——转自 慢慢学TensorFlow 微信公众号