设计模式之享元模式

来源:互联网 发布:易观千帆数据哪来的 编辑:程序博客网 时间:2024/06/04 20:15

享元模式(Flyweight),运用共享技术有效地支持大量细粒度的对象。

也就是说,在一个系统中如果有多个相同的对象,那么只共享一份就可以了,不必每个都去实例化一个对象。

比如说一个文本系统,每个字母定一个对象,那么大小写字母一共就是52个,那么就要定义52个对象。如果有一个1M的文本,那么字母是何其的多,如果每个字母都定义一个对象那么内存早就爆了。那么如果要是每个字母都共享一个对象,那么久大大节约了资源。


Flyweight类,它是所有具体享元类的父类或接口,通过这个接口,Flyweight可以接受并作用于外部状态。

public abstract class Flyweight {    public abstract void operation();}

ConcreteFlyweight是继承Flyweight父类或实现Flyweight接口,并为内部状态增加存储空间。

public class ConcreteFlyweight extends Flyweight {    private String mStr;    public ConcreteFlyweight(String str) {        mStr = str;    }    @Override    public void operation() {        System.out.println("具体享元: " + mStr);    }}

UnsharedConcreteFlyweight是指那些不需要共享的Flyweight子类。因为Flyweight接口共享成为可能,但它并不强制共享。

public class UnsharedConcreteFlyweight extends Flyweight {    private String mStr;    public UnsharedConcreteFlyweight(String str) {        mStr = str;    }    @Override    public void operation() {        System.out.println("不共享的Flyweight: " + mStr);    }}

FlyweightFactory,是一个享元工厂,用来创建并管理Flyweight对象。它主要是用来确保合理地共享Flyweight,当用户请求一个Flyweight时,FlyweightFactory对象提供一个已创建的实例或者创建一个(如果不存在的话)。

public class FlyweightFactory {    private HashMap<String, Flyweight> mFlyweights = new HashMap<String, Flyweight>();    public Flyweight getFlyweight(String key) {        if (!mFlyweights.containsKey(key)) {            mFlyweights.put(key, new ConcreteFlyweight(key));        }        return mFlyweights.get(key);    }    public int getFlyweigtCount() {        int count = mFlyweights.size();        System.out.println("享元个数:" + count);        return count;    }}

调用:

FlyweightFactory factory = new FlyweightFactory();Flyweight fa = factory.getFlyweight("google");fa.operation();Flyweight fb = factory.getFlyweight("google");fb.operation();Flyweight fc = factory.getFlyweight("apple");fc.operation();Flyweight fd = factory.getFlyweight("google");fd.operation();UnsharedConcreteFlyweight uf = new UnsharedConcreteFlyweight("banana");uf.operation();factory.getFlyweigtCount();

输出结果:

具体享元: google具体享元: google具体享元: apple具体享元: google不共享的Flyweight: banana享元个数:2

在享元对象内部并且不会随环境改变而改变的共享部分,可以称为是享元对象的内部状态;

随环境改变而改变的、不可以共享的状态就是外部状态。

享元模式可以避免大量非常相似类的开销。在程序设计中,有时需要生成大量细粒度的类实例来表示数据。

如果能发现这些实例除了几个参数基本上都是相同的,有时就能够大幅度地减少需要实例化的类的数量。

如果能把那些参数移到类实例的外面,在方法调用时将它们传递进来,就可以通过共享大幅度地减少单个实例的数目。

如果一个应用程序使用了大量的对象,而大量的这些对象造成了很大的存储开销时就应该考虑使用;

还有就是对象的大多数状态可以是外部状态,如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象,此时可以考虑使用享元模式。

在Java语音中,String类型就是使用了享元模式。String对象是final类型,对象一旦创建就不可改变。在Java中字符串常量都是存在常量池中,Java会确保一个字符串常量在常量池中只有一个拷贝。经典例子如:

String s1 = "hello";String s2= "hello";System.out.println("s1和s2是同一个对象吗:" + s1.equals(s2));

输出结果是:true。

0 0