博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
揭秘设计模式:享元模式(FlyWeight)的学习与理解(2)
阅读量:6566 次
发布时间:2019-06-24

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

hot3.png

    链接地址:

    在上一篇:中,我简单的介绍了一下享元模式,享元模式的设计理念包括应用其实并不明确,我也有知其然不知其所以然的感觉,今天通过参阅书籍和网上的一些例子,来整理一下享元模式,争取摸索出个所以然来。

    看到一些关于设计模式的书籍上,都有享元模式的种类,说什么分为:单纯享元模式和复合享元模式,我也并不是特别理解,简单来理解:单纯享元模式就是所有享 元对象都可共享,像上一篇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
 flyweights = Collections            .synchronizedMap(new HashMap
());     // 也可以使用hashtable    //private HashTable
 flyweights = new HashTable
();     public FlyweightFactory() {    }     /**     * 获取享元对象     *      * @Title: getFlyWeight     * @author Realfighter     * @date 2014-8-4 下午04:53:33     * @param obj     * @return Flyweight     */    public Flyweight getFlyWeight(Object obj) {        Flyweight flyweight = (Flyweight) flyweights.get(obj);        if (flyweight == null) {            // 产生新的ConcreteFlyweight            flyweight = new ConcreteFlyweight((String) obj);            flyweights.put(obj, flyweight);        }        return flyweight;    }     /**     * 获取享元对象的实际数量     *      * @Title: getFlyweightSize     * @author Realfighter     * @date 2014-8-4 下午04:52:56     * @return int     */    public int getFlyweightSize() {        return flyweights.size();    } }

    这样,我们已经通过代码实现了一个简单的享元模式,我们新建一个客户端角色来测试一下,如下:

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

    总结:我们提供了六种外部状态和三种内部状态,享元工厂为我们创建了三个享元对象,实现了相同对象的共享,这大概就是享元模式吧。示例中的代码也参阅了网 络上的一些关于享元模式的博客,个人感觉享元模式挺重要的,不过在开发中使用的机会应该不会太多,个人对其的理解也比较片面晦涩,不一定能做到真正的理 解,大致懵懵懂懂吧。

转载于:https://my.oschina.net/realfighter/blog/349738

你可能感兴趣的文章
我设计的网站的分布式架构
查看>>
linux extract rar files
查看>>
Knockout.Js官网学习(监控属性Observables)
查看>>
ORA-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务解决
查看>>
azure之MSSQL服务性能测试
查看>>
Android BitmapFactory.Options
查看>>
前端构建:Less入了个门
查看>>
phonegap(cordova) 自己定义插件代码篇(三)----支付宝支付工具整合
查看>>
linux 批量进行:解压缩某一类压缩文件类型的文件
查看>>
激活modelsim se 10.4 时运行patch_dll.bat不能生成TXT
查看>>
17秋 软件工程 Alpha 事后诸葛亮会议
查看>>
线性空间
查看>>
疑似checkpoint堵塞数据库连接
查看>>
Node.js中针对中文的查找和替换无效的解决方法
查看>>
理解指针的关键
查看>>
如何查看Ubuntu下已安装包版本号
查看>>
我的那些年(2)~我毕业了
查看>>
VS2017 配置ImageMagick
查看>>
Hive任务优化--控制hive任务中的map数和reduce数
查看>>
[摄影]上海往事
查看>>