享元模式(FlyWeight)
定义
运用共享技术有效地支持大量细粒度的对象。
UML类图
角色
抽象享元(Flyweight)角色 :给出一个抽象接口,以规定出所有具体享元角色需要实现的方法。
具体享元(ConcreteFlyweight)角色:实现抽象享元角色所规定出的接口。如果有内蕴状态的话,必须负责为内蕴状态提供存储空间。
享元工厂(FlyweightFactory)角色 :本角色负责创建和管理享元角色。本角色必须保证享元对象可以被系统适当地共享。当一个客户端对象调用一个享元对象的时候,享元工厂角色会检查系统中是否已经有一个符合要求的享元对象。如果已经有了,享元工厂角色就应当提供这个已有的享元对象;如果系统中没有一个适当的享元对象的话,享元工厂角色就应当创建一个合适的享元对象。
例子
用户类
package com.csdhsm.pattemdesign.flyweight; /** * @Title: User.java * @Description: 用户类 * @author: Han * @date: 2016年7月1日 上午8:50:54 */ 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; } }
网站抽象类,充当FlyWeight
package com.csdhsm.pattemdesign.flyweight; /** * @Title: WebSite.java * @Description: 网站抽象类 * @author: Han * @date: 2016年7月1日 上午8:53:39 */ public abstract class WebSite { public abstract void user(User user); }
具体网站实现类,充当ConcreteFlyweight
package com.csdhsm.pattemdesign.flyweight; /** * @Title: ConcreteWebsite.java * @Description: 具体网站类 * @author: Han * @date: 2016年7月1日 上午8:53:53 */ public class ConcreteWebsite extends WebSite { private String name = ""; public ConcreteWebsite(String name) { this.name = name; } @Override public void user(User user) { System.out.println("网站分类: " + name + " 用户: " + user.getName()); } }
网站享元工厂类,FlyweightFactory
package com.csdhsm.pattemdesign.flyweight; import java.util.HashMap; /** * @Title: WebSiteFactory.java * @Description: 网站享元工厂类 * @author: Han * @date: 2016年7月1日 上午8:55:37 */ public class WebSiteFactory { private HashMap<String, WebSite> flyWeights = new HashMap<>(); 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(); } }
客户端
package com.csdhsm.pattemdesign.flyweight; public class Solution { public static void main(String[] args) { WebSiteFactory factory = new WebSiteFactory(); WebSite xm = factory.getWebSiteCategory("产品展示"); xm.user(new User("小明")); WebSite xh = factory.getWebSiteCategory("产品展示"); xh.user(new User("小红")); WebSite xx = factory.getWebSiteCategory("产品展示"); xx.user(new User("小溪")); WebSite xc = factory.getWebSiteCategory("博客"); xc.user(new User("小陈")); WebSite xl = factory.getWebSiteCategory("博客"); xl.user(new User("小李")); WebSite xg = factory.getWebSiteCategory("产品展示"); xg.user(new User("小侯")); System.out.println("网站总数为 " + factory.getWebSiteCount()); } }
结果
OK,可以看见,在享元工厂里的网站被共享了
总结
享元模式的优点在于它大幅度地降低内存中对象的数量。
享元模式的缺点是
1使得系统更加复杂。为了使对象可以共享,需要将一些状态外部化,这使得程序的逻辑复杂化。
2将享元对象的状态外部化,而读取外部状态使得运行时间稍微变长。