demo描述:现有网站,不同的人登进去显示会有不同,如果每登一个用户就new一个用户和网站的话会使网站有很多相同的东西冗余,导致很耗内存。享元模式将共有的东西(内部状态)提出来存在享元对象内部共用,将变化的东西(外部状态)放到对象外边,内、外部状态结合起来用,解决重复对象内存耗费的问题。内部+外部状态=完整用户登录的网站
demo代码:
享元工厂,用于构建一个池容器,提供从池中获取对象的方法,。(工厂:new出来后做了别的操作,外界不用再new,拿来即用)
public class WebSiteFactory {
//集合,充当池的作用
private HashMap<String ,ConcreteWebSite> pool =new HashMap<>();
//根据网站发布形式,返回一个网站,如果没有就创建一个网站,并放入池中
public WebSite getWebSiteCategory(String type){
if (!pool.containsKey(type)){
//*创建公共部分并存入缓存池
pool.put(type,new ConcreteWebSite(type));
}
return (WebSite)pool.get(type);
}
//获取网站分类的总数(池中有多少个网站类型)
public int getWebSiteCount(){
return pool.size();
}
}
抽象的享元角色,定义内部状态(共享东西放子类里了)和外部状态(通过use方法使用到被共享的东西)
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 class Client {
public static void main(String[] args) {
//创建一个工厂
WebSiteFactory factory = new WebSiteFactory();
WebSite webSite1 = factory.getWebSiteCategory("新闻");
webSite1.use(new User("小一"));
webSite1.use(new User("大一"));
WebSite webSite2 = factory.getWebSiteCategory("博客");
webSite2.use(new User("小二"));
webSite2.use(new User("大二"));
System.out.println("网站的分类共" + factory.getWebSiteCount() + "个");
}
}
demo类图:
类图分析:1处可扩展,由于将类型属性传入了构造方法内,所有可根据传入类型不同得到不同的类。1处是工厂的产品,作用可以联想简单工厂,只不过产品还要供外部状态访问,与外部状态组合起来形成一个完整的网站(相同的网站,不同的用户不同的使用)
适用场景:系统中有大量对象,并且有明显的内、外部状态区分时可用
总结:享元模式用共享技术支持大量细粒度对象,解决对象的内存浪费问题。与单例区别:单例是整个对象被共享,使用者不关心对象有什么,拿来即用;享元是对象部分被共享-内部状态,部分需要使用者参与-外部状态,对使用者来说部分透明