三个月没学编程的班花找到了人称“设计模式扛把子”的Tony老师,并发誓一定要把享元模式搞明白。
Q:享元模式的享元是什么意思?
A:所谓享元就是共享对象(别想歪了),享元模式的关键即提供一个包含各种对象的池,那么不管某个对象你创建多少遍,其实都是最开始创建并存到享元池里的那一个。
Q:听不懂,能举个例子吗?
A:比如作为全公司唯一的程序员的你接到任务需要开发一些网页,包括三个技术博客网页,五个体育新闻网页,两个英语学习网页,四个LeetCode索引网页等等,最直接最无脑的做法就是一个网页一个网页的做,一个一个连接数据库,一个一个申请空间,这样做的弊端肯定是造成大量的对服务器资源的浪费,而且人也累得够呛。因为这样做忽略了网页的大量的相同的元素。而如果采取享元模式的做法,遇到相同类型的网页,只需要从对象池中取出之前已经创建好的,并按照实际修饰即可。
Q:有个地方不太懂,比如技术博客,你创建的三个都是完全一样的吗?那这样还有什么意义呢?
A:问题很尖锐嘛,我们规定享元对象的状态有两个,即内部状态和外部状态。内部状态就是处于对象内部而且不会随环境改变而改变的共享部分,这也是享元工厂检索对象的一个指标。而外部状态则随环境改变而改变,且不可以共享。我三个技术博客,可能登录的用户是完全不一样的,这个用户就是所谓的外部状态。外部状态需要单独写。
Q:明白了,谢谢老师,能帮我落实到UML和代码设计吗?我初学不太会。
没问题。
UML图很关键你记住,这是帮助我们梳理思路和整理设计模式的关键工具。
这个示例的主题就是多个网页设计。
首先是抽象类WebSite,作为享元模式具体功能类的抽象父类。
package coding;
public abstract class WebSite {
abstract public void use(User user);
}
其次是具体内部状态实现类:
package coding;
public class ConcreteWebSite extends WebSite{
private String name;
public ConcreteWebSite(String name) {
this.name = name;
}
public void use(User user)
{
System.out.println(name+"正在使用..用户是"+user.getName());
}
}
然后是外部状态,与其他类没有任何关联:
package coding;
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;
}
}
然后就是享元工厂类,这里使用hashmap作为检索工具,当检索不到就在hashmap内创建一个,检索到了就直接使用。这正是享元模式的核心。
package coding;
import java.util.HashMap;
public class ConcreteFactory {
private String type;
private HashMap<String,WebSite> hash=new HashMap();
public WebSite getWebSiteCategory(String type)
{
if(!hash.containsKey(type))
{
hash.put(type,new ConcreteWebSite(type));
return hash.get(type);
}
return hash.get(type);
}
}
最后,客户
package coding;
public class Client {
public static void main(String[] args) {
//build factory
ConcreteFactory fac=new ConcreteFactory();
WebSite web1=fac.getWebSiteCategory("南华足球报");
web1.use(new User("Eric"));
WebSite web2=fac.getWebSiteCategory("南华足球报");
web2.use(new User("许老板"));
WebSite web3=fac.getWebSiteCategory("今日新闻");
web3.use(new User("pony"));
}
}
后续:老师,我有个朋友想认识你。
这个朋友就是你吧。。。