Flyweight (享元)模式 -------- 共享对象,避免浪费

》》

    ------ flyweight 是“轻量级”的意思。对象在计算机中是虚拟存在的东西,它的“重”和“轻”并非指实际重量,

           而是它们“所使用的内存大小”。使用内存多的对象就是“重”对象,使用内存少的对象就是“轻”对象。

    ------ 当程序中需要大量对象时,如果都使用 new 关键字来分配内存,将会消耗大量内存空间

    ------ Flyweight 模式:通过尽量共享实例来避免 new 出实例。当需要某个实例时,并不总是通过 new 

          关键字来生成实例,而是尽量共用已经存在的实例。(Flyweight 模式的核心内容)。

 

》》示例程序

      在示例程序中,有一个将许多普通字符组合成为的“大型字符”的类,它的实例就是重实例。为了进行

   测试,我们以文件形式保存了大型字符'0'~'9'和‘-’的字符数据。效果如下:

    

   

   

    

 

》》类的一览表

  --------- BigChar 是表示“大型字符”的类。它会从文件中读取大型字符的字体数据,并将它们保存在内存中,

            然后使用 print 方法输出大型字符。大型字符会消耗很多内存,因此我们需要考虑如何共享 BigChar

             类的实例。

   --------- BigCharFactory 类会根据需要生成 BigChar 类的实例。不过如果它发现之前已经生成了某个大型

            字符的 BigChar 类的实例,则会直接利用该实例,而不是再生成新的实例。此外,为了能够快速查

            找出之前是否已经生成了某个大型字符所对应的实例,使用 java.util.Hashmap 类。

    --------- BigString 类用于将多个 BigChar 组成“大型字符串”。

    --------- Main 类是用于测试程序行为的类。

》》BigChar 类

    

package flyweight;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * BigChar 类是表示“大型字符”的类
 */

public class BigChar {
    private char charname;                       //  字符名字
    private String fontdata;                     //  大型字符对应的字符串(由 # .\n 组成)

    public BigChar(char charname){                // 构造函数
        this.charname = charname;

        try {
            BufferedReader reader = new BufferedReader(
                    new InputStreamReader(this.getClass().getResourceAsStream("big"+charname+".txt"))

            );

            String line;
            StringBuffer buf = new StringBuffer();

            while((line = reader.readLine())!= null){
                buf.append(line);
                buf.append("\n");
            }
            reader.close();
            fontdata = buf.toString();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void print(){
        System.out.println(fontdata);             // 显示大型字符
    }
}

》》BigCharFactory 类

    

package flyweight;

/**
 * 1. BigCharFactory 类是生成 BigChar 类的实例的工厂。它实现了共享实例的功能。
 * 2 .pool 字段用于管理已生成的 BigChar 类的实例。
 * 3. 在 BigCharFactory 类中,使用 java.util.HashMap  类来管理“字符串--》实例”之间的对应关系。使用
 *      java.util.HashMap 类的 put 方法可以将某个字符串(键)与一个实例(值)关联起来,就可以通过键来
 *      获取它相应的值。
 *
 */

import java.util.HashMap;

public class BigCharFactory {
    private HashMap pool = new HashMap();                            // 管理已生成的 BigChar 的实例
    private static BigCharFactory singleton = new BigCharFactory();  // Singleton 模式
    private BigCharFactory(){};                                       // 构造函数

    public static BigCharFactory getInstance(){
        return singleton;                                            // 获取唯一的实例
    }


    public synchronized BigChar getBigChar(char charname){         // 生成(共享)BigChar 类的实例
        BigChar bc = (BigChar)pool.get(""+charname);

        if(bc == null){
            bc = new BigChar(charname);
            pool.put(""+charname,bc);
        }
        return bc;
    }

}

》》BigString 类

package flyweight;

/**
 *  BigString 类表示由 BigChar 组成的“大型字符串”的类
 */

public class BigString {
    private BigChar[] bigChars;               // "大型字符"的数组

    public BigString(String string){           // 构造函数
        bigChars = new BigChar[string.length()];

        BigCharFactory factory = BigCharFactory.getInstance();

        for(int i = 0 ; i < bigChars.length ; i++){
            bigChars[i] = new BigChar(string.charAt(i));


        }

    }

    public void print(){                      // 显示
        for(int i = 0 ; i < bigChars.length ; i++){
            bigChars[i].print();
        }
    }
}

》》Main 类

 

package flyweight;

/**
 * 测试程序
 */
public class Main {
    public static void main(String[] args){
        String  stringValue = "2123";

        BigString bigString = new BigString(stringValue);
        bigString.print();

    }
}

》》Flyweight 模式中的登场角色

   ------ Flyweight (轻量级)

           按照通常方式编写程序会导致程序变重,所以如果能够共享实例会比较好,而 Flyweight 角色

      表示的就是那些实例会被共享的类。在上面的程序中,由 BigChar 类扮演此角色。

   ------ FlyweightFactory (轻量级工厂)

            FlyweightFactory 角色是生成 Flyweight 角色的工厂。在工厂中生成的 Flyweight 角色可以实现

      共享实例。在上面的程序中,由  BigCharFactory 类扮演此角色。

    ------ Client (请求者)

             Client 角色使用 FlyweightFactory 角色来生成 Flyweight 角色。在上面的示例程序中,由

       BigString 类扮演此角色。

》》扩展思路的要点

     -------- 对多个地方产生影响

               **** 如果要改变被共享的对象,就会多个地方产生影响。也就是说,一个实例的而改变会同时

                    反映到使用该实例的地方。

               **** 共享的特点:修改一个地方会对多个地方产生影响。

               **** 设计者在使用 Flyweight 模式共享信息时必须仔细思考应当共享哪些信息

     -------- Intrinsic 与 Extrinsic

                **** 应当共享的信息被称为  Intrinsic 信息。它指的是不论实例在哪里、不论在什么情况下都

                不会改变的信息,或是不依赖实例状态的信息。

                **** 不应当共享的信息被称为 Extrinsic 信息。它是指当实例的位置、状况发生改变时会变化的

                 信息,或是依赖于实例状态的信息。

                **** 

                  

     -------- 不要让被共享的实例被垃圾回收器回收了

                  **** 在上面的示例程序中,BigCharFactory 类中,我们使用 java.util.HashMap 来管理已经生成

                  的 BigChar  的实例。像这样在 java 中自己“管理”实例时,必须注意“不要让实例被垃圾回收器回收了”

                  **** 在 Java  程序中可以通过 new 关键字分配内存空间。如果分配了过多内存,就会导致内存不足。

                  这时,运行 Java 程序的虚拟机就会开始垃圾回收处理。它会查看自己的内存空间(堆空间)中是否

                  在没有被使用的实例,如果存在就释放该实例,这样就可以回收可用的内存空间。

      ------- 内存之外的其他资源

                 ***** 在上面的示例程序中,我们了解到共享实例可以减少内存使用量。一般来说,共享实例可以减少

                 所需资源的使用量。这里的资源指的是计算机中的资源,而内存是资源中的一种。

                 ***** 时间也是一种资源。使用 new 关键字生成实例会花费时间。通过 Flyweight 模式共享实例可以

                 减少使用 new 关键字生成实例的次数。这样,就可以提高程序运行速度。

                  ***** 文件句柄(文件描述符)和窗口句柄等也都是一种资源。在操作系统中,可以同时使用的文件

                 句柄和窗口句柄是有限制的。因此,如果不共享实例,应用程序在运行时很容易达到资源极限而导致

                  崩溃。

》》相关的设计模式

         -------- Proxy 模式

                    如果生成实例的处理需要花费较长时间,那么使用 Flyweight 模式可以提高程序的处理速度。而

                Proxy 模式则是通过设置代理提高程序的处理速度。

         -------- Composite 模式

                有时候可以使用 Flyweight 模式共享 Composite 模式中的 Leaf 角色。

         ------- Singleton 模式

                 在 FlyweightFactory 角色中有时候会使用 Singleton 模式。

  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小达人Fighting

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值