21.Flyweight模式

[TOC]

Flyweight

面向对象技术可以很好地解决一些灵活性或可扩展性问题,但在很多情况下需要在系统中增加类和对象的个数。当对象数量太多时,将导致运行代价过高,带来性能下降等问题。享元模式(Flyweight)正是为解决这一类问题而诞生的。享元模式通过共享技术实现相同或相似对象的重用。

在享元模式中可以共享的相同内容称为内部状态(Intrinsic State),而那些需要外部环境来设置的不能共享的内容称为** 外部状态(Extrinsic State),其中外部状态和内部状态是相互独立的,外部状态的变化不会引起内部状态的变化*。

由于区分了内部状态和外部状态,因此可以通过设置不同的外部状态使得相同的对象可以具有一些不同的特征,而相同的内部状态是可以共享的。

也就是说,享元模式的本质是分离与共享 :分离变与不变,并且共享不变

把一个对象的状态分成内部状态和外部状态,内部状态即是不变的,外部状态是变化的;然后通过共享不变的部分,达到减少对象数量并节约内存的目的。

在享元模式中通常会出现工厂模式,需要创建一个享元工厂来负责维护一个享元池(Flyweight Pool)(用于存储具有相同内部状态的享元对象)。

在享元模式中,共享的是享元对象的内部状态,外部状态需要通过环境来设置。

在实际使用中,能够共享的内部状态是有限的,因此享元对象一般都设计为较小的对象,它所包含的内部状态较少,这种对象也称为 细粒度对象。

享元模式的目的就是使用共享技术来实现大量细粒度对象的复用。尽量共享实例来减少new出新实例。

通用类图

image

示例代码

  • Flyweight接口
public interface Flyweight {
    // 一个示意性方法,参数state是外蕴状态
    public void attachState(String state);
}
  • ConcreteFlyweight
public class ConcreteFlyweight implements Flyweight {
    private Character intrinsicState = null;

    public ConcreteFlyweight(Character state) {
        this.intrinsicState = state;
    }

    /**
     * 外蕴状态作为参数传入方法中,改变方法的行为, 但是并不改变对象的内蕴状态。
     */
    @Override
    public void attachState(String state) {
        System.out.println("intrinsicState is " + this.intrinsicState.toString());
        System.out.println("Extrinsic State = " + state);
    }

}
  • FlyweightFactory
public class FlyweightFactory {
    // 对象池
    private Map fwpool = new HashMap();
    private Lock lock = new ReentrantLock();

    public Flyweight getObject(Character state) {
        lock.lock();
        Flyweight fly = fwpool.get(state);
        if (fly == null) {
            fly = new ConcreteFlyweight(state);
            fwpool.put(state, fly);
        }
        lock.unlock();
        return fly;
    }
}
  • Client
public class Client {
    public static void main(String[] args) {
        FlyweightFactory factory = new FlyweightFactory();
        Flyweight fly = factory.getObject(new Character('a'));
        fly.attachState("First Call");

        fly = factory.getObject(new Character('b'));
        fly.attachState("Second Call");

        fly = factory.getObject(new Character('a'));
        fly.attachState("Third Call");
    }
}

小结

简单来说,就是通过对象的池化来共享。但是在共享之前需要划分出那些需要被共享,哪些不能被共享,所以需要将信息细化之后再放进对象池中供其他的对象分享。

参考资料

[1] http://blog.csdn.net/justloveyou_/article/details/55045638

你可能感兴趣的:(21.Flyweight模式)