享元模式:
运用共享技术有效地支持大量细粒度的对象。
// 网站抽象类
public abstract class WebSite {
public abstract void use(User u);
}
// 具体网站类
public class ConcreteWebSite extends WebSite {
private String name;
public ConcreteWebSite(String name) {
this.name = name;
}
@Override
public void use(User u) {
System.out.println("the type of Website: " + name + ", user: " + u.getName());
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
// 产生网站的工厂
public class WebSiteFactory {
private Map<String, WebSite> flyWeights = new HashMap<String, WebSite>();
// this is the key method ,it confirm that there is only one instance of the same website.
public WebSite getWebSiteCategory(String key) {
if (!flyWeights.containsKey(key)) {
flyWeights.put(key, new ConcreteWebSite(key));
}
return flyWeights.get(key);
}
public int getWebSiteCount() {
return flyWeights.size();
}
}
// 用户类
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 FlyWeightMain {
public static void main(String[] args) {
WebSiteFactory wf = new WebSiteFactory();
WebSite webSite1 = wf.getWebSiteCategory("show product");
webSite1.use(new User("Lincoln"));
WebSite webSite2 = wf.getWebSiteCategory("Blog");
webSite2.use(new User("Lincoln"));
WebSite webSite3 = wf.getWebSiteCategory("Blog");
webSite3.use(new User("Jim6"));
WebSite webSite4 = wf.getWebSiteCategory("Blog");
webSite4.use(new User("Kenny"));
System.out.println("total website: " + wf.getWebSiteCount());
}
}
什么时候用享元模式:
1. 如果一个应用程序使用了大量的对象,而大量的这些对象造成了很大的存储开销就应该考虑使用。
2. 对象的大多数状态为外部状态,如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象,此时可以考虑使用享元模式。
具体应用:
围棋和五子棋只有黑白两色,所以颜色应该是棋子的内部状态,而各个棋子之间的差别主要就是位置的不同,所以方位坐标应该是棋子的外部状态,对于围棋,一盘棋理论上有361个空位可以放棋子,那如果用常规的面向对象来编程,每盘棋都可能有两三百个棋子对象产生,一台服务器就很难支持更多的玩家玩围棋游戏了,毕竟内存空间是有限的,如果用享元模式来处理棋子,那么棋子对象就可以减少到只有两个实例。