一:背景
在系统中,当需要大量重复的细粒度对象时,我们往往可以只维护一个实例;这样不仅避免了创建大量重复对象对资源的浪费,也易于我们的维护和拓展。
二:概述
1、定义
运用共享技术有效地支持大量细粒度的对象。
2、类图结构
三:实例分析
拿网站建设例子来说,有时候,我们创建的一系列网站(流量小)都是结构十分相似、功能又相近的,这种情况下,往往就可以使用同一个网站的实例;
我们使用一个网站工厂来管理和维护我们的网站。
对应代码:
网站工厂
public class WebsiteFactory {
private Hashtable flyweights = new Hashtable();
//获取网站分类
public Website getWebsiteCatagory(String key){
if (!flyweights.contains(key)){
flyweights.put(key, new ConcreteWebsite(key));
}
return (Website) flyweights.get(key);
}
//获取网站分类总数
public int getWebsiteCount(){
return flyweights.size();
}
}
网站(包含共享的数据和不会共享的内容)
public abstract class Website {
public abstract void use(User user);
}
不会发生共享的数据,例如用户
public class User {
private String name;
public User(String name){
this.name = name;
}
public String getName() {
return name;
}
}
具体网站实现者
public class ConcreteWebsite extends Website {
private String name = "";
public ConcreteWebsite(String name){
this.name = name;
}
@Override
public void use(User user) {
System.out.println("网站分类:"+name+" ;用户:"+user.getName());
}
}
客户端调用:
WebsiteFactory f = new WebsiteFactory();
Website fx = f.getWebsiteCatagory("产品展示");
fx.use(new User("段誉"));
Website fy = f.getWebsiteCatagory("产品展示");
fx.use(new User("虚竹"));
Website fz = f.getWebsiteCatagory("博客");
fz.use(new User("杨过"));
Website fl = f.getWebsiteCatagory("博客");
fl.use(new User("周伯通"));
System.out.println("网站分类总数为:"+f.getWebsiteCount());
结果为:
网站分类:产品展示 ;用户:虚竹
网站分类:博客 ;用户:杨过
网站分类:博客 ;用户:周伯通
网站分类总数为:2
享元模式可以避免大量非常相似类的开销,如果我们使用的大量实例除了几个参数外基本上相同,我们就可以把这些参数迁移到类实例的外面,在方法调用时将它们传递进来(如例子中的user),这样就可以通过共享大幅度减少单个实例的数目。
ThreadPool 线程池 与数据库连接池 都有使用享元模式。
参考书籍:《大话设计模式》