链接地址:
在上一篇:中,我简单的介绍了一下享元模式,享元模式的设计理念包括应用其实并不明确,我也有知其然不知其所以然的感觉,今天通过参阅书籍和网上的一些例子,来整理一下享元模式,争取摸索出个所以然来。
看到一些关于设计模式的书籍上,都有享元模式的种类,说什么分为:单纯享元模式和复合享元模式,我也并不是特别理解,简单来理解:单纯享元模式就是所有享 元对象都可共享,像上一篇String类的例子;复合享元模式就是部分享元对象可共享,像Integer对象的例子。
不过享元模式共享的重点,就是区分出内部状态(intrinsic)和外部状态(extrinsic),内部状态通常是指包含在享元内部的、对象本身的状态,不会随享元环境变化,是不变可共享的;外部状态是享元对象之外的状态,会根据享元的场景而变化,不可共享。
要学习享元模式,首先需要理解享元模式的结构图,如下:
上面的结构图中,包含了五个角色,它们分别是:
Flyweight:抽象享元角色,是所有具体享元类的超类,是接口或抽象类,并不强制子类实现共享。提供参数用于接收需要外部状态的操作。
ConcreateFlyweight:具体享元角色,抽象享元角色的实现,如果有内部状态的话,必须负责为内部状态提供存储空间,享元对象的内部状态必须与对象所处的周围环境无关,从而使得享元对象可以在系统内共享。
UnsharablConcreteFlyweight:复合享元角色,其所代表的对象是不可以共享的。
FlyweightFactory:享元工厂角色,负责创建和管理享元角色,其必须保证享元对象可以被系统适当的共享。
Client:客户端角色,用于请求享元对象,需要自行存储所有享元对象的外部状态。
接下来,我们通过代码来进一步的理解享元模式,首先我们抽象出一个享元角色,我们将其设计为接口,代码如下:
package javase.flyweight; /** * 抽象享元角色 * * @Package javase.flyweight * @ClassName: Flyweight * @author Realfighter * @date 2014-8-4 下午04:39:47 */public interface Flyweight { /** * extrinsicState:外部状态 * * @Title: operation * @author Realfighter * @date 2014-8-4 下午04:44:42 * @param extrinsicState * String */ public String operation(String extrinsicState); }
然后我们需要实现具体的享元角色,如下:
package javase.flyweight; /** * 具体享元对象角色 * * @Package javase.flyweight * @ClassName: ConcreteFlyweight * @author Realfighter * @date 2014-8-4 下午04:41:58 */public class ConcreteFlyweight implements Flyweight { private String intrinsicState;// 内部状态 public ConcreteFlyweight(String intrinsicState) { this.intrinsicState = intrinsicState; } /** * 外部状态传入 * * @Title: operation * @author Realfighter * @date 2014-8-4 下午04:47:30 * @param extrinsicState * @return */ public String operation(String extrinsicState) { String str = "内部状态:" + intrinsicState + ";外部状态:" + extrinsicState; return str; }}
之后我们需要提供一个享元工厂,用来创建和管理享元对象,代码如下:
package javase.flyweight; import java.util.Collections;import java.util.HashMap;import java.util.Map; /** * 享元工厂角色 * * @Package javase.flyweight * @ClassName: FlyweightFactory * @author Realfighter * @date 2014-8-4 下午04:49:30 */public class FlyweightFactory { // 使用同步的map集合,线程安全 private Map
这样,我们已经通过代码实现了一个简单的享元模式,我们新建一个客户端角色来测试一下,如下:
package javase.flyweight; /** * 客户端角色 * * @Package javase.flyweight * @ClassName: Client * @author Realfighter * @date 2014-8-4 下午05:07:00 */public class Client { FlyweightFactory factory = new FlyweightFactory(); Flyweight fly1; Flyweight fly2; Flyweight fly3; Flyweight fly4; Flyweight fly5; Flyweight fly6; public Client() { // 三种内部状态:u love me1,u love me2,u love me3 fly1 = factory.getFlyWeight("u love me 1"); fly2 = factory.getFlyWeight("u love me 2"); fly3 = factory.getFlyWeight("u love me 3"); fly4 = factory.getFlyWeight("u love me 1"); fly5 = factory.getFlyWeight("u love me 2"); fly6 = factory.getFlyWeight("u love me 3"); } public void doFlyweight() { // 六种外部状态i love u 123456 System.out.println(fly1.operation("i love u 1")); System.out.println(fly2.operation("i love u 2")); System.out.println(fly3.operation("i love u 3")); System.out.println(fly4.operation("i love u 4")); System.out.println(fly5.operation("i love u 5")); System.out.println(fly6.operation("i love u 6")); System.out.println("享元对象数量:" + factory.getFlyweightSize()); } public static void main(String[] args) { Client client = new Client(); client.doFlyweight(); } }
测试结果如下:
内部状态:u love me 1 ;外部状态:i love u 1 内部状态:u love me 2 ;外部状态:i love u 2 内部状态:u love me 3 ;外部状态:i love u 3 内部状态:u love me 1 ;外部状态:i love u 4 内部状态:u love me 2 ;外部状态:i love u 5 内部状态:u love me 3 ;外部状态:i love u 6 享元对象数量: 3 |
总结:我们提供了六种外部状态和三种内部状态,享元工厂为我们创建了三个享元对象,实现了相同对象的共享,这大概就是享元模式吧。示例中的代码也参阅了网 络上的一些关于享元模式的博客,个人感觉享元模式挺重要的,不过在开发中使用的机会应该不会太多,个人对其的理解也比较片面晦涩,不一定能做到真正的理 解,大致懵懵懂懂吧。