享元模式: 场景:内存属于稀缺资源,如果有很多个完全相同或相似的对象,我们可以通过享元模式来节省内存。
核心:享元模式以共享的方式高效地支持大量细粒度对象的重用。 享元对象能做到共享的关键字是区分了内部状态和外部状态。
内部状态:可以共享,不会随着环境变化而改变。
外部状态:不可以共享,会随着环境变化而改变。
享元模式的实现:
1.FlyweightFactory享元工厂类:创建并管理享元对象,享元池一般设计成键值对
2.FlyWeight抽象享元类:通常是一个接口或抽象类,声明公共方法,这些方法可以向外界提供对象的内部状态,设置对象的外部状态。
3.ConcreteFlyweight具体享元类:为内部状态提供的成员变量进行存储。
4.UnsharedConcreteFlyWeight非共享享元类:不能被共享的子类可以设计成为非共享享元类。
应用场景:线程池、数据库连接池、String类的设计。
优点:极大的减少内存中对象的数量。相同或相似的对象内存中只有一份,一个实例可以提供许多虚拟实例,极大的节约资源,提高系统的性能。
外部状态相对独立,不影响内部状态。
缺点:模式较复杂。使程序的逻辑复杂化,每次读取外部状态使运行时间变长,用时间换取了空间。
一旦实现了享元模式,单个逻辑实例将无法拥有独立的行为。
看一个简单明了的Demo:
/**
* 享元类
* @author wxisme
*
*/
public interface FlyWeight {
void setSex(String sex);
String getSex();
void display(Character c);
}
/**
* 具体享元类 获取内部状态、设置外部状态
* @author wxisme
*
*/
class HumanFlyWeight implements FlyWeight {
private String sex;
public HumanFlyWeight(String sex) {
super();
this.sex = sex;
}
@Override
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String getSex() {
return sex;
}
@Override
public void display(Character c) {
System.out.println(c.getCharacter() + "的" + sex + "。");
}
}
/**
* 外部状态
* @author wxisme
*
*/
public class Character {
private String character;
public Character(String character) {
super();
this.character = character;
}
public String getCharacter() {
return character;
}
public void setCharacter(String character) {
this.character = character;
}
}
import java.util.HashMap;
import java.util.Map;
/**
* 享元工厂类
* @author wxisme
*
*/
public class HumanFlyWeightFactory {
static Map<String, FlyWeight> map = new HashMap<>();
public static FlyWeight getHuman(String sex) {
if(map.get(sex) != null) {
return map.get(sex);
}
else {
FlyWeight h = new HumanFlyWeight(sex);
map.put(sex, h);
return h;
}
}
}
public class Client {
public static void main(String[] args) {
HumanFlyWeightFactory factory = new HumanFlyWeightFactory();
//实质是共享相同的内部状态,封装变化的外部状态,节省资源。
FlyWeight flyweight1 = factory.getHuman("女人");
FlyWeight flyweight2 = factory.getHuman("女人");
//两个只包含相同内部状态的对象其实是一个对象。
System.out.println(flyweight1);
System.out.println(flyweight2);
//设置变化的外部状态。
flyweight1.display(new Character("性感"));
flyweight2.display(new Character("漂亮"));
}
}
运行结果:
com.wxisme.flyweight.HumanFlyWeight@1fe3ee3
com.wxisme.flyweight.HumanFlyWeight@1fe3ee3
性感的女人。
漂亮的女人。