问题引入:
网站的设计,例:博客,写博客的人非常多,而且虽然每个人的博客的用户和内容不同(外部状态不同),但所有博文的页面布局等却都是相似甚至相同的(内部状态是一样的),倘若每一个人在写博客时都新实例化一个博客的对象是不现实的,会耗费大量的资源。又如在为客户设计网站时,有大量的企业提出了做网站的要求,但所对网站的要求类似,在这种情况下,倘若为每一家企业都申请空间,用不同的数据库,将类似要求的代码复制,这么做是不现实的。
一、网站例子最开始的代码到享元模式
1、最开始的一一实例化的代码:
网站类:
class Website
{private String name;
public Website(String name)
{this.name=name;
}
public void use()
{System.out.println("网站类型"+name);
}
}
客户端:
public static void main(String [] args)
{Website a=new Website("产品展示");
a.use();
Website b=new Website("产品展示");
b.use();
Website c=new Website("博客");
c.use();
Website d=new Website("博客"); //每一个类都进行了实例化,像"博客",其实所有博文的页面布局都差不多,只是内容不同而已,所以没必要每次都实例化
d.use();
2、享元模式下的代码:
抽象网站类:
abstract class Website
{
public abstract void use(User user);
}
具体网站类:(内部状态,可共享)
class Concretewebsite extends Website
{private String name;
public Concretewebsite(String name)
{
this.name=name;
}
public void use(User user) {
System.out.println("用户:"+user.GetName()+" "+"网站分类:"+name);
}
}
用户类:(外部状态,不可共享)每篇博文的账号不同,内容不同
class User
{
private String name;
public User(String name) {
this.name=name;
}
public String GetName() {
return name;
}
}
网站工厂类:(将页面布局、功能不同的设计内容调价到Map中,假如有十个客户都要求设计一个“博客”网站,就只许实例化一个“博客”网站对象就行了)
class WebsiteFactory
{private Map<String,Website>map=new HashMap<String,Website>();
public Website GetWebsite(String key) {
if(!map.containsKey(key))
{Concretewebsite website=new Concretewebsite(key);
map.put(key, website);
}
return map.get(key);
}
}
客户端:
public static void main(String[] args) {
WebsiteFactory factory=new WebsiteFactory();
Website f1=factory.GetWebsite("产品展示");
f1.use(new User("小郝"));
Website f2=factory.GetWebsite("博客");
f2.use(new User("小张"));
}
显示:
二、享元模式的优缺点及应用
优点及应用:
如果一个应用程序用了大量对象,就应该考虑享元模式;如果对象的大多数状态可以外部状态,如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多对象,可以考虑用(例如“博客”网站:每篇博文的布局等都差不多,所以都用一个或少量就行,但每篇博文都有不同的账号和内容,而且差距很大)
倘若只要设计两三个网站,就没有必要了
缺点:
享元模式需要维护一个记录了系统已有的所有享元的列表,这本身便消耗资源,而且享元模式使系统更加复杂,为了达到共享,需要将一些状态外部化(从客户要求中找出那些是变化的,那些是变化少甚至不变的),使程序逻辑更加复杂化。