享元模式(Flyweight Pattern)
,运用共享技术有效的支持大量的细粒度对象。换句话说,使用享元模式对相同或者类似的对象进行复用,以此来减少少相同或者类似的对象的创建数量,从而减少内存占用,提高性能。
享元模式属于结构型模式。
在具体了解前先介绍两个名词:
有些时候又把享元模式分成单纯的享元模式和复合享元模式,下面分别介绍。
单纯享元模式,也就是说所有的具体享元类都是可以被共享的,不存在不可以共享的具体享元类。
单纯享元模式的UML类图如下:
享元工厂最好使用单例模式实现。
package io.github.brightloong.lab.design.flyweight;
/**
* FlyWeight class
* 定义享元类接口
* @author BrightLoong
* @date 2018/6/11
*/
public interface FlyWeight {
/**
* 操作方法.
* @param extrinsicState 外部状态
*/
public void operation(String extrinsicState);
}
package io.github.brightloong.lab.design.flyweight;
/**
* ConcreteFlyWeight class
*
* @author BrightLoong
* @date 2018/6/11
*/
public class ConcreteFlyWeight implements FlyWeight {
/**内部状态*/
private String intrinsicState;
/**
* 构造方法,并设置内部状态.
* @param intrinsicState
*/
public ConcreteFlyWeight(String intrinsicState) {
this.intrinsicState = intrinsicState;
}
@Override
public void operation(String extrinsicState) {
System.out.println("内部状态:" + intrinsicState);
System.out.println("外部状态:" + extrinsicState);
}
}
package io.github.brightloong.lab.design.flyweight;
import java.util.HashMap;
import java.util.Map;
/**
* FlyWeightFactory class
* 用于创建和管理享元对象,本身是单例的。
* @author BrightLoong
* @date 2018/6/11
*/
public class FlyWeightFactory {
/**唯一的factory实例*/
private static FlyWeightFactory factory = new FlyWeightFactory();
/**用于保存享元对象的map*/
private Map flyWeights = new HashMap<>();
/**
* 私有的构造函数
*/
private FlyWeightFactory() {}
/**
* 返回FlyWeightFactory唯一实例.
* @return
*/
public static FlyWeightFactory getInstance() {
return factory;
}
/**
* 单纯享元模式工厂方法.
* @param state key
* @return
*/
public FlyWeight getFlyWeight(String state) {
FlyWeight flyWeight = flyWeights.get(state);
if (flyWeight == null) {
flyWeight = new ConcreteFlyWeight(state);
flyWeights.put(state, flyWeight);
}
return flyWeight;
}
}
package io.github.brightloong.lab.design.flyweight;
/**
* Client class
*
* @author BrightLoong
* @date 2018/6/11
*/
public class Client {
public static void main(String[] args) {
FlyWeightFactory factory = FlyWeightFactory.getInstance();
FlyWeight flyWeight1 = factory.getFlyWeight("a");
FlyWeight flyWeight2 = factory.getFlyWeight("b");
FlyWeight flyWeight3 = factory.getFlyWeight("a");
FlyWeight flyWeight4 = factory.getFlyWeight("c");
//flyWeight1和flyWeight3具有相同的内部状态a,使用同一个实例,下面结果输出true
System.out.println(flyWeight1 == flyWeight3);
//不同的外部状态从方法传入
flyWeight2.operation("hello");
flyWeight2.operation("hi");
}
}
输出结果如下:
true
内部状态:b
外部状态:hello
内部状态:b
外部状态:hi
复合享元模式,将一些单纯享元使用组合模式加以组合,可以形成复合享元对象,这样的复合享元对象本身不能共享,但是它们可以分解成单纯享元对象,而后者则可以共享。
复合享元模式中,组成复合享元对象的每个单纯享元对象拥有自己的内部状态,而每个单纯享元对象的外部状态都和复合享元对象的外部状态相同。所以复合享元模式可以对多个单纯享元对象设置相同的外部状态, 这也是复合享元模式的应用场景。
复合享元模式的UML类图如下:
接口和单纯享元类的代码在上面已经列出了,下面是其他相关代码。
package io.github.brightloong.lab.design.flyweight;
import java.util.HashMap;
import java.util.Map;
/**
* CompositeConcreteFlyweight class
*
* @author BrightLoong
* @date 2018/6/11
*/
public class CompositeConcreteFlyweight implements FlyWeight {
Map flyWeights = new HashMap<>();
/**
* flyWeights是单纯享元对象的集合,它们具有相同的外部状态extrinsicState,
* 调用的时候使用循环调用单纯享元对象的operation方法
* @param extrinsicState 外部状态
*/
@Override
public void operation(String extrinsicState) {
for (Map.Entry entry : flyWeights.entrySet()) {
entry.getValue().operation(extrinsicState);
}
}
/**
* 添加单纯享元对象.
* @param state
* @param flyWeight
*/
public void add(String state, FlyWeight flyWeight) {
flyWeights.put(state, flyWeight);
}
/**
* 移除单纯享元对象.
* @param state
*/
private void remove(String state) {
flyWeights.remove(state);
}
}
package io.github.brightloong.lab.design.flyweight;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* FlyWeightFactory class
* 用于创建和管理享元对象,本身是单例的。
* @author BrightLoong
* @date 2018/6/11
*/
public class FlyWeightFactory {
/**唯一的factory实例*/
private static FlyWeightFactory factory = new FlyWeightFactory();
/**用于保存享元对象的map*/
private Map flyWeights = new HashMap<>();
/**
* 私有的构造函数
*/
private FlyWeightFactory() {}
/**
* 返回FlyWeightFactory唯一实例.
* @return
*/
public static FlyWeightFactory getInstance() {
return factory;
}
/**
* 单纯享元模式工厂方法.
* @param state key
* @return
*/
public FlyWeight getFlyWeight(String state) {
FlyWeight flyWeight = flyWeights.get(state);
if (flyWeight == null) {
flyWeight = new ConcreteFlyWeight(state);
flyWeights.put(state, flyWeight);
}
return flyWeight;
}
/**
* 复合享元模式工厂方法.
* @param states
* @return
*/
public FlyWeight getFlyWeight(List states) {
CompositeConcreteFlyweight flyWeight = new CompositeConcreteFlyweight();
for (String state : states) {
//调用了单纯享元模式工厂方法,所以使用flyWeight.add加入的单纯享元对象是可以共享的
flyWeight.add(state, this.getFlyWeight(state));
}
return flyWeight;
}
}
package io.github.brightloong.lab.design.flyweight;
import java.util.ArrayList;
import java.util.List;
/**
* Client2 class
*
* @author BrightLoong
* @date 2018/6/11
*/
public class Client2 {
public static void main(String[] args) {
FlyWeightFactory factory = FlyWeightFactory.getInstance();
List states = new ArrayList<>();
states.add("a");
states.add("b");
states.add("c");
FlyWeight flyWeight = factory.getFlyWeight(states);
FlyWeight flyWeight2 = factory.getFlyWeight(states);
//并不相等,输出false,复合享元对象不可共享
System.out.println(flyWeight == flyWeight2);
//多个单纯享元对象具有相同的外部状态hello
flyWeight.operation("hello");
}
}
输出结果如下:
false
内部状态:a
外部状态:hello
内部状态:b
外部状态:hello
内部状态:c
外部状态:hello
Java中String就是对享元模式的应用,如下代码会输出true。
String a = "Hello Word";
String b = "Hello Word";
System.out.println(a == b);