享元模式,也叫蝇量模式:运用共享技术有效支持大量细粒度的对象。享元模式能够解决重复对象的内存浪费问题,对象放在一个池子中,需要的时候就取出来,不会重复创建对象。
享元模式的类图:
享元模式的角色:
Flyweight:抽象的享元角色,需要将对象的信息划分为内部状态和外部状态,并定义接口。
ConcreteFlyweight:具体的享元角色
UnsharedConcreteFlyweight:不可共享的角色,一般不会出现在享元工厂
FlyweightFactory:享元工厂类,创建一个池容器,从池中获取对象。
享元模式需要将对象的信息划分为内部状态和外部状态:
内部状态指对象共享出来的信息,存储在享元对象内部并且不会随环境的改变而改变。
外部状态指对象得以依赖的一个标记,是随环境改变而改变的、不可共享的状态。
享元模式的使用场景:系统中有大量对象,消耗大量内存,而且对象的状态大部分可以外部化时可以考虑使用享元模式。
案例:一个网站有多个种类,而且每个网站有多个访问者,现在需要编写用户程序实现访问的功能。
思路分析:如果每个用户访问的时候都要创建一个网站对象,那么就会占用大量内存,浪费内存空间,因此适合用享元模式去解决,用hashmap存储创建的对象,需要的时候直接从hashmap中取得对象,不需要再重复创建。
抽象享元角色
public abstract class Website {
public abstract void use(User user);
}
具体享元角色
public class ConcreteWebSite extends Website {
private String type="";
public ConcreteWebSite(String type) {
this.type = type;
}
@Override
public void use(User user) {
System.out.println("网站发布的形式:"+type+" 使用者:"+user.getName());
}
}
一个外部状态
public class User {
private String name;
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
享元工厂
public class WebsiteFactory {
//集合,充当池的作用
private HashMap<String,Website> pool=new HashMap<>();
//根据网站的类型,返回一个网站,如果没有就创建一个网站,并放入到池中
public Website getWebsiteCategory(String type){
if(!pool.containsKey(type)){
pool.put(type,new ConcreteWebSite(type));
}
return pool.get(type);
}
//查看池中网站的总数
public int WebSiteCount(){
return pool.size();
}
}
客户端调用
public class Client {
public static void main(String[] args) {
WebsiteFactory websiteFactory=new WebsiteFactory();
Website website= websiteFactory.getWebsiteCategory("电商");
website.use(new User("Tom"));
Website website2=websiteFactory.getWebsiteCategory("电商");
website2.use(new User("Jack"));
Website website3= websiteFactory.getWebsiteCategory("博客");
website3.use(new User("Tom"));
System.out.println("创建的实例个数"+websiteFactory.WebSiteCount());
}
}
结果: