享元模式 Java

一个类A有诸多的成员变量,创建一个A对象需要在堆中为该对象分配空间。假设,需要创建十万个A对象,那么A的成员变量中,有没有一成不变的某些数据的组合呢?如果能够将这些数据组合加以类型化——称为轻量级或鸿毛/羽毛/Flyweight对象,那么十万个A对象可以共享Flyweight对象,从而有效地降低内存开销。

Flyweight设计模式,直译为轻量级、鸿毛模式,意译为共享单元模式简称享元模式。


属性对象

假设Car对象有如下属性:

     String owner;//车主,例程中略

     String name;//车型名称

     Color color;//车的颜色

     int X,Y; //GPS定位坐标

     int length,width,height;//车体的几何尺寸

如果创建十几个Car对象,我们不需要过多考虑。如果创建武汉市所有轿车的对象,那么Car对象的成员变量就需要仔细分析。①GPS定位坐标X和Y,是每时每刻都在变化的,不考虑共享;车主owner,大多数Car的owner是私人,除非owner是公交或的士公司才考虑它;车的颜色变化也比较多;②车型名称和车体的几何尺寸,这种数据组合是固定的,虽然奥迪A6和奥迪A4分别有不同取值,但数据组合是固定的。于是,可以设计一个鸿毛flyweight类型,用于保存数据组合。
package property.flyweight;
public interface ICarUnit{
    public String getName();
    public double getHeight();
    public double getWidth();
    public double getLength();
    public void printMess(String mess);
}//具体子类暂缓
ICarUnit对象将被Car对象共享。例如,创建的表示奥迪A6、奥迪A4、东风标致2008、东风标致4008的羽毛对象都将被共享。

如何管理共享的对象?

通常

  • 每种享元对象仅创建一个,而且可以通过一个HashMap管理这些对象。
  •  外界不得创建享元对象,而是使用HashMap所管理的共享对象。

因而,管理共享对象的工作,抽象并封装成一个类。GoF中,称其为享元工厂(FlyweightFactory),而yqj2065通常称其为享元池(FlyweightPool)

享元工厂这一称呼,从内部说明了该类包含一个静态工厂,并按照HashMap的key获得羽毛对象,如方法

public static synchronized  ICarUnit getFlyweight(String key)

享元池这一称呼,从外界用户的感受,说明该类的作用就是维护一个对象池。真正持有数据的享元CarUnit(即ICarUnit的实现类),因为和享元池/享元工厂关系密切,通常设计为享元池的内部类。
package property.flyweight;
import java.util.HashMap;
public class FlyweightPool{
    private static  HashMap<String,ICarUnit>  hashMap;
    static{hashMap=new HashMap<String,ICarUnit>();}
    private FlyweightPool(){    }
    public static synchronized ICarUnit getUnit(String name,double length,double width,double height){
        String key = name;
        if(hashMap.containsKey(key))
            return hashMap.get(key);
        else{
            ICarUnit flyweight = new CarUnit(name,width,height,length);
            hashMap.put(key,flyweight);
            return flyweight;
        }
    }
    
    static final class CarUnit implements ICarUnit{
        private String name;
        private double width;
        private double height;
        private double length; 
        private CarUnit(String name,double width,double height,double length){
            this.name =name;
            this.width=width;
            this.height=height;
            this.length=length;
        }

        public String getName(){         return name;        }
        public double getHeight(){       return height;        }
        public double getWidth(){        return width;        }
        public double getLength(){       return length;        }

        public void printMess(String mess){
            System.out.print(mess);        //输出外部数据mess
            System.out.print(" 宽度:"+width);  //输出内部数据width
            System.out.print(" 高度:"+height);
            System.out.println("长度:"+length);
        }
    }
}

JVM中的享元

Integer 、 Byte、Short、Long和Character使用了享元模式。Character (from 0 to 127) 、其他(from -128 to 127)。而最典型的则是String。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值