享元模式
运用共享技术有效的支持大量细粒度的对象
使用场景
1、系统中有大量对象。
2、这些对象消耗大量内存。
3、这些对象的状态大部分可以外部化。
4、这些对象可以按照内蕴状态分为很多组,当把外蕴对象从对象中剔除出来时,每一组对象都可以用一个对象来代替。
5、系统不依赖于这些对象身份,这些对象是不可分辨的。
优点:大大减少对象的创建,降低系统的内存,使效率提高。
缺点:提高了系统的复杂度,需要分离出外部状态和内部状态,而且外部状态具有固有化的性质,不应该随着内部状态的变化而变化,否则会造成系统的混乱。
实现示例
叙述:创建一个网站可以分别用于不用的产品分类,当创建三个不同的网站时,如果不采用享元模式,则需要复制三分创建网站的代码,当用了设计模式时,可以把创建网站这部分代码提取出来共用;根据不同的分类参数去创建相关实例
创建网站抽象类
public interface WebSite {
void use(User user);
}
具体网站创建
public class ConcreteWebSite implements WebSite {
private String name;//网站名
ConcreteWebSite(String name){
this.name=name;
}
@Override
public void use(User user) {
System.out.println("网站分类:"+name+"用户:"+user.getName());
}
}
网站使用者(相当于分类分别拥有不同的网站)
public class User {
private String name;
User(String name){
this.name=name;
}
}
享元工厂
public class WebSiteFactory {
private HashMap flyweights = new HashMap(16);
//创建网站实例
public WebSite getWebSite(String type){
if(!flyweights.containsKey(type))
flyweights.put(type,new ConcreteWebSite(type));
return (WebSite)flyweights.get(type);
}
//统计网站个数
public int getSiteCount(){
return flyweights.size();
}
}
客户端
public class MainTest {
public static void main(String[] args){
WebSiteFactory factory = new WebSiteFactory();
WebSite fx = factory.getWebSite("产品展示");
fx.use(new User("小菜"));
WebSite fy = factory.getWebSite("产品展示");
fx.use(new User("大鸟"));
WebSite fz = factory.getWebSite("博客");
fx.use(new User("阿娇"));
WebSite fb = factory.getWebSite("博客");
fx.use(new User("阿呀"));
System.out.println("创建网站数量:"+factory.getSiteCount());
}
}
//结果
网站分类:产品展示用户:小菜
网站分类:产品展示用户:大鸟
网站分类:产品展示用户:阿娇
网站分类:产品展示用户:阿呀
创建网站数量:2
根据示例结果可知:上述代码基本实现了享元模式的目的 只要网站分类 ‘博客’ “产品展示” 不变 我们创建的都是一个网站实例;另外还能引入两个概念如下
内部状态与外部状态
在享元对象内部并且不会随环境改变而改变的共享部分称之为内部状态
随着环境改变而改变的、不可以共享的状态就是外部状态
上述user为外部状态,website则为内部状态