目录
一:享元模式
1.引出问题
在看完单例模式,我们知道单例模式在容器运行期间,会产生一个唯一的实例化对象,这样避免了在全局使用时产生多个相同的对象而产生资源浪费的问题。但是在实际生产中,我们需要的往往是这些单独的对象的集合管理,就不如字典数据,我管理的是字典数据的一个集合,但是同时字典数据又是对全局应用全局可见可用彷佛又符合单例模式的样子。终于解决案例,我们可以来参照java的String的生命周期。
在java中的String拥有很特殊的存储方式:常量池。常量池的存储String使得每创建一个Srting就会比对,该字符串存在否,存在则直接拿过来使用,否则就创建一个新的。
参照常量池的方法,我们是不是可以来创建一个单例池来股那里这些单例的集合对象呢?而单例池同时又会有什么问题呢?这个会在结尾讨论。
2.引出概念
享元抽象类:用于对外提供抽象方法或者接口。
享元具体类:用来实现抽象类。
享元工厂:用来管理享元对象的,创建或者管理享元对象生命周期的。
状态:享元模式分为内外部状态。实则就是通过外部的一个key值来判断内部值的存在与否。
二:代码详解
1.抽象类
package r;
/**
* 享元抽象类
*
*/
public abstract class Flyweight {
//内部状态
public String intrinsic;
//外部状态
protected final String extrinsic;
//要求享元角色必须接受外部状态
public Flyweight(String extrinsic) {
this.extrinsic = extrinsic;
}
//定义业务操作
public abstract void operate(int extrinsic);
public String getIntrinsic() {
return intrinsic;
}
public void setIntrinsic(String intrinsic) {
this.intrinsic = intrinsic;
}
}
2.抽象实现类
package r;
/*
* 抽象享元的实现
*/
public class FlyweightImpl extends Flyweight{
public FlyweightImpl(String extrinsic) {
super(extrinsic);
}
@Override
public void operate(int extrinsic) {
System.err.println("你要实现具体的操作");
}
}
3.工厂
package r;
import java.util.HashMap;
import java.util.Map;
/*
* 享元工厂类
* (1)享元模式的核心
* (2)用来创建和管理享元对象的生命周期
* (3)合理提供一个外部请求的已存在和或者刚创建的享元对象
*/
public class FlyweightFactory {
//创建一个池容器
private static Map<String, Flyweight> pool=new HashMap<>();
//享元工厂
public static Flyweight getFlyweight(String extrinsic) {
Flyweight flyweight = null;
if(pool.containsKey(extrinsic)) { //池中有该对象
flyweight = pool.get(extrinsic);
System.out.print("已有 " + extrinsic + " 直接从池中取---->");
} else {
//根据外部状态创建享元对象
flyweight = new FlyweightImpl(extrinsic);
//放入池中
pool.put(extrinsic, flyweight);
System.out.print("创建 " + extrinsic + " 并从池中取出---->");
}
return flyweight;
}
}
4.测试
package r;
public class test {
public static void main(String[] args) {
int extrinsic = 22;
Flyweight flyweightX = FlyweightFactory.getFlyweight("X");
Flyweight flyweightY = FlyweightFactory.getFlyweight("Y");
Flyweight flyweightZ = FlyweightFactory.getFlyweight("Z");
Flyweight flyweightReX = FlyweightFactory.getFlyweight("X");
}
}
三:说明
1.代码说明
在一和二中,我们似乎对于内外部状态解释的不是太清楚。现在我们一工厂实际实现来说明。 我们看到工厂的实现是基于map的,判断key的存在来思想那存或取,那么这个key值是哪来的?就是外部状态,而内部对象value就是内部状态
2.产生的问题
(1)基于String的存储的方式,我们可以String的存储并没有携带key值?
(2)就是关于生命周期,我们手动创建的池,池中对象的生命周期需要我们手动回收?
3.解决方案
(1)针对第一个问题我们如果使用 map存储的存储,那么我们可以直接指定一个属性作为key值实际上这个和上面的方法是没有区别。可以提供以下思路:存储不以Map,而是以Set或者List或者队列来存储(建议使用list或队列,下面会说明原因)。
(2)针对第二个问题实际上如果我们设计了全局变量,我们可以不用考虑生命周期的问题,如果实在是要去考虑,
a.我们可以在对象创建时携带一个time工具,实现在30min后手动销毁对象。
b.实际上如果我们以list来存储,我们可以设置list长度,如果超长了,我们只需重置list的长度数据。实际上用队列实现时
最优方案。