设计模式学习笔记--享元(Flyweight)模式(一)

2014-11-23 23:31:26 · 作者: · 浏览: 0


写在模式学习之前


什么是设计模式:在我们进行程序设计时,逐渐形成了一些典型问题和问题的解决方案,这就是软件模式;每一个模式描述了一个在我们程序设计中经常发生的问题,以及该问题的解决方案;当我们碰到模式所描述的问题,就可以直接用相应的解决方法去解决这个问题,这就是设计模式。

设计模式就是抽象出来的东西,它不是学出来的,是用出来的;或许你根本不知道任何模式,不考虑任何模式,却写着最优秀的代码,即使以“模式专家”的角度来看,都是最佳的设计,不得不说是“最佳的模式实践”,这是因为你积累了很多的实践经验,知道“在什么场合代码应该怎么写”,这本身就是设计模式。

有人说:“水平没到,学也白学,水平到了,无师自通”。诚然,模式背熟,依然可能写不出好代码,更别说设计出好框架;OOP理解及实践经验到达一定水平,同时也意味着总结了很多好的设计经验,但"无师自通",却也未必尽然,或者可以说,恰恰是在水平和经验的基础上,到了该系统的学习一下“模式”的时候了,学习一下专家总结的结果,印证一下自己的不足,对于提高水平还是很有帮助的。

本系列的设计模式学习笔记,实际是对于《Java与模式》这本书的学习记录。


享元模式的定义


享元模式以共享的方式高效地支持大量的细粒度对象。

享元对象能做到共享的关键是区分内部状态(Internal State)和外部状态(External State)。

一个内部状态是存储在享元对象内部的,并且是不会随环境改变而有所不同的。因此,一个享元可以具有内部状态并可以共享。

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

外部状态不可以影响享元对象的内部状态。它们是相互独立的。

分类:

根据所涉及的享元对象的内部表象,享元模式可以分为单纯享元模式和复合享元模式。

应用场景:

享元模式在编辑器系统中大量使用。比如,用来将每一个字母做成一个享元对象,提供多种字体。

在Java语言中,String也使用了享元模式。在JVM内部,String对象是共享的,如果两个String对象所包含的字符串相同,JVM实际只创建了一个String对象提供给两个引用,从而实现了String对象的共享。在堆内存中,这两个String对象的地址;以及栈内存中,这两个String对象引用的地址,都是完全一致的。String的intern()方法给出这个字符串在共享池中的唯一实例。

如下可证:

String a="123";String b = "123";则a==b和a.equals(b)都是成立的;当然如果我们强制new新的堆内存,则不一致,比如String c = new String("123");则a==c是不成立的,但是a.equals(c)是成立的,说明a和c所的代表的值相等,但是a和c指向不同的栈地址空间。


单纯享元模式


结构图


vcfJq6O6tMu9x8mrysfL+dPQtcS+38zlz+3Uqr3Hyau1xLOswOCjrM6q1eLQqcDguea2qLP20OjSqsq1z9a1xLmrubK907/aoaPEx9Cp0OjSqs3isr/XtMystcSy2df3v8nS1M2ouf2199HQyczStbe9t6jS1LLOyv3Qzsq9tKvI66GjPC9wPgo8cD6jqDKjqb7fzOXP7dSqo6hDb25jcmV0ZUZseXdlaWdodKOpvcfJq6O6yrXP1rPpz/PP7dSqvcfJq8v5uea2qLXEvdO/2qGjyOe5+9PQxNqyv9e0zKy1xLuwo6yx2NDruLrU8M6qxNqyv9e0zKzM4bmptOa0or/VvOSho8/t1Kq21M/ztcTE2rK/17TMrLHY0OvT67bUz/PL+bSmtcTW3M6nu7e+s87eudijrLTTtvjKubXDz+3UqrbUz/Mgv8nS1NTaz7XNs8TaubLP7aGjPGJyPgo8L3A+CjxwPqOoM6Opz+3Uqrmks6ejqEZseXdlaWdodEZhY3Rvcnmjqb3Hyaujuri61PC0tL2ous253MDtz+3Uqr3Hyauho8/t1Kq5pLOnsdjQ67Gj1qTP7dSqttTP87/J0tSxu8+1zbPKyrWxtdi5ss/toaO1sdK7uPa/zbuntsu21M/ztffTw9K7uPbP7dSqttTP88qxo6zP7dSquaSzp73Hyau74bzssunPtc2z1tDKx7fx0tG+rdPQ0ru49rf7us/SqsfztcTP7dSqttTP86GjyOe5+9PQo6y+zczhuanV4rj20tHT0LXEz+3UqrbUz/Oju8jnufvDu9PQo6y+zbS0vajSu7j2z+3UqrbUz/Ohozxicj4KPC9wPgo8cD6jqDSjqb/Nu6e2y6OoQ2xpZW50o6m9x8mro7ogv827p7WlvcfJq9Do0qrOrLuk0ru49rbUy/nT0M/t1Kq21M/ztcTS/dPDo6zQ6NKq19TQ0LTmtKLL+dPQz+3UqrbUz/O1xM3isr/XtMysoaM8YnI+CjwvcD4KPHA+PGJyPgo8L3A+CjxoMj60+sLryrXP1jwvaDI+CjxwPjwvcD4KPHByZSBjbGFzcz0="brush:java;">import java.util.*; abstract class Flyweight { //一个示意性的方法,参数state是外部状态 public abstract void operation(String state); } class ConcreteFlyweight extends Flyweight { private Character intrinsicState = null; //构造函数,内部状态作为参数传入 public ConcreteFlyweight(Character state) { this.intrinsicState = state; } //外部状态作为参数传入,改变方法的行为,但不改变对象的内部状态 public void operation(String state) { { } System.out.println("Intrinsic State = " + intrinsicState + ",Extrinsic State = " + state); } } class FlyweightFactory { private Map files = new HashMap (); private Flyweight lnkFlyweight; public FlyweightFactory() {} public Flyweight factory(Character state) { if(files.containsKey(state)) { return files.get(state); } else{ Flyweight fly = new ConcreteFlyweight(state); files.put(state,fly); return