6. 享元模式(Flyweight Pattern)
享元模式也并不复杂,它的作用主要是为了节省开销而设计的,它避免了产生拥有相同内容的大量的"小类",改为大家都共用同一个类。
享元模式将系统中的对象的装态分为内蕴状态(intrinsic)和外蕴状态(extrinsic)两种,内蕴状态是可以不会随着运行环境的变化而变化的,而外蕴状态则相反,所以,内蕴状态可以用来共享,而外蕴状态只能由客户端来保存,可以在必要时传给享元进行某些操作。
享元模式的结构主要包括下面的几个部分:
首先,是享元的接口,
- public interface Flyweight {
-
- public void operate(ExternalState externalState);
-
- }
public interface Flyweight {
public void operate(ExternalState externalState);
}
然后是Flyweight的具体实现类,
- public class ConcreteFlyweight implements Flyweight {
- private InternalState internalState;
-
- @Override
- public void operate(ExternalState externalState) {
- System.out.println("operating is performed");
- }
-
- }
public class ConcreteFlyweight implements Flyweight {
private InternalState internalState;
@Override
public void operate(ExternalState externalState) {
System.out.println("operating is performed");
}
}
这个类内部就包括了一个可以共享的"内部状态"了。
这个就是可以用来共享的享元了。但是,还会有不用于共享的,也有一些本身不能共享但是内部状态是由一系列享元构成的"符合享元"。
- public class UnsharedConcreteFlyweight implements Flyweight {
-
- private ExternalState externalState;
-
- private Flyweight flyweightState1;
-
- private Flyweight flyweightState2;
-
- @Override
- public void operate(ExternalState externalState) {
- System.out.println("operating is performed");
- }
-
- }
public class UnsharedConcreteFlyweight implements Flyweight {
private ExternalState externalState;
private Flyweight flyweightState1;
private Flyweight flyweightState2;
@Override
public void operate(ExternalState externalState) {
System.out.println("operating is performed");
}
}
最后是一个Flyweight的Factory,实现了一个Flyweight池的功能,
- public class FlyweightFactory {
-
- private Map<Object, Flyweight> flyweights = new HashMap<Object, Flyweight>();
-
- public Flyweight getFlyweight(Object key) {
- Flyweight flyweight = flyweights.get(key);
- if (flyweight == null) {
-
- flyweight = new ConcreteFlyweight();
- flyweights.put(key, flyweight);
- }
- return flyweight;
- }
-
- }
public class FlyweightFactory {
// Flyweight pool
private Map<Object, Flyweight> flyweights = new HashMap<Object, Flyweight>();
public Flyweight getFlyweight(Object key) {
Flyweight flyweight = flyweights.get(key);
if (flyweight == null) {
// 产生新的ConcreteFlyweight
flyweight = new ConcreteFlyweight();
flyweights.put(key, flyweight);
}
return flyweight;
}
}
最后,客户端就可以重复的使用享元了,
- public class Client {
-
- public static void main(String[] args) {
- FlyweightFactory factory = new FlyweightFactory();
-
- for (int i = 0; i < 10000; i++) {
- Flyweight flyweight = factory.getFlyweight("key");
- flyweight.operate();
- }
-
- }
-
- }
public class Client {
public static void main(String[] args) {
FlyweightFactory factory = new FlyweightFactory();
for (int i = 0; i < 10000; i++) {
Flyweight flyweight = factory.getFlyweight("key");
flyweight.operate();
}
}
}
这样,相同的"key"就可以共享同一个对象了。
使用享元模式时,要注意内蕴状态和外蕴状态的划分,外蕴状态一定不能用来共享。另外只有在使用大量对象并因此造成了性能开销的情况下才有必要使用享元模式。
最后,给出享元模式的类图: