享元模式

享元模式

享元模式(Flyweight),运用共享技术有效地支持大量细粒度的对象。

享元模式的核心思想其实就是共享,节省内存,减少开销,例如项目中的对象共享,利用享元工厂维护已经创建的或者预先创建的对象,当需要时再去该工厂里拿即可。

享元对象状态分为内部状态和外部状态。引用大话设计模式的一段话,清楚地理解内部状态和外部状态的区别。

享元模式可以避免大量非常相似类的开销。在程序设计中,有时需要生成大量细粒度的类实例来表示数据。如果能发现这些实例除了几个参数外基本上都是相同的,就能够大幅度地减少需要实例化的类的数量。如果能把这些参数移到类实例的外面,在方法调用时将它们传递进来,就可以通过共享大幅度地减少单个实例的数目。

还是举例来说明,假设网站包括博客系统和在线书店两种类型,博客和在线书店都是网站,网站是通过用户账号登录的。因此用户账号就是网站的外部状态,那么网站的内部状态是什么呢?其实就是博客和在线书店本身,看下类图:

UML类图

享元模式_第1张图片

WebSite作为网站抽象基类,通过方法参数传入用户,作为网站的外部状态。ConcreteWebSite实现了WebSite抽象基类,并提供了私有字段type-网站类型作为网站的内部状态。FlyweightFactory作为享元工厂提供了共享对象的存储和获取,接着看代码实现。

代码实现

首先看下网站抽象基类WebSite

WebSite

/**
 * 

文件描述: 网站抽象类

* * @Author luanmousheng * @Date 17/11/12 下午10:39 */
public abstract class WebSite { abstract void use(User user); }

用户类

User

/**
 * 

文件描述: 用户类

* * @Author luanmousheng * @Date 17/11/12 下午10:53 */
public class User { private String name; private Integer age; public User(String name, Integer age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }

具体网站类

ConcreteWebSite

/**
 * 

文件描述: 具体网站类

* * @Author luanmousheng * @Date 17/11/12 下午10:42 */
public class ConcreteWebSite extends WebSite { //网站类型,eg: blog、book_shop private String type; public ConcreteWebSite(String type) { this.type = type; } @Override public void use(User user) { System.out.println("user: " + user.getName() + " use web type: " + type); } }

享元工厂类

FlyweightFactory

/**
 * 

文件描述: 享元工厂

* * @Author luanmousheng * @Date 17/11/12 下午10:47 */
public class FlyweightFactory { //存储共享对象,网站类型为key private HashMap flyweights = new HashMap<>(); public WebSite getWebSite(String type) { if (type == null) { throw new IllegalArgumentException("param is null"); } if (!flyweights.containsKey(type)) { flyweights.put(type, new ConcreteWebSite(type)); } return flyweights.get(type); } }

测试类

FlyweightDemo

/**
 * 

文件描述: 享元模式Demo

* * @Author luanmousheng * @Date 17/11/12 下午10:48 */
public class FlyweightDemo { public static void main(String[] args) { FlyweightFactory flyweightFactory = new FlyweightFactory(); WebSite blogWeb = flyweightFactory.getWebSite("blog"); blogWeb.use(new User("tom", 23)); blogWeb.use(new User("linda", 19)); WebSite bookShopWeb = flyweightFactory.getWebSite("book_shop"); bookShopWeb.use(new User("jack", 20)); } }

测试类输出结果:

user: tom use web type: blog
user: linda use web type: blog
user: jack use web type: book_shop

测试结果显示共享了类型为blog的网站。

享元模式的思路很简单,但是作用确不简单。系统共享对象较多时可以考虑使用该模式,否则引入享元模式只会增加代码的复杂度,得不偿失。

参考

  1. 大话设计模式 程杰

你可能感兴趣的:(设计模式)