本文共 3219 字,大约阅读时间需要 10 分钟。
在面向对象程序设计过程中,有时会面临要创建大量相同或相似对象实例的问题。创建那么多的对象将会耗费很多的系统资源,它是系统性能提高的一个瓶颈。
例如,围棋和五子棋中的黑白棋子,图像中的坐标点或颜色,局域网中的路由器、交换机和集线器,教室里的桌子和凳子等。这些对象有很多相似的地方,如果能把它们相同的部分提取出来共享,则能节省大量的系统资源,这就是享元模式的产生背景。
享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。
享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象。
享元模式的定义提出了两个要求,细粒度和共享对象。因为要求细粒度,所以不可避免地会使对象数量多且性质相近,此时我们就将这些对象的信息分为两个部分:内部状态和外部状态。
比如,连接池中的连接对象,保存在连接对象中的用户名、密码、连接URL等信息,在创建对象的时候就设置好了,不会随环境的改变而改变,这些为内部状态。而当每个连接要被回收利用时,我们需要将它标记为可用状态,这些为外部状态。
享元模式的本质是缓存共享对象,降低内存消耗。
享元模式的主要角色有如下:
定义非共享元角色:
package com.siyi.flyweightpattern;//非享元角色public class UnsharedConcreteFlyweight { private String info; UnsharedConcreteFlyweight(String name) { this.info = name; } public String getInfo() { return info; } public void setInfo(String info) { this.info = info; }}
定义抽象共享元:
package com.siyi.flyweightpattern;//抽象享元角色public interface Flyweight { public void operation(UnsharedConcreteFlyweight state);}
定义具体共享元:
package com.siyi.flyweightpattern;//具体享元角色public class ConcreteFlyweight implements Flyweight { private String key; ConcreteFlyweight(String key) { this.key = key; System.out.println("具体享元:" + key + "被创建!"); } @Override public void operation(UnsharedConcreteFlyweight outState) { System.out.print("具体享元" + key + "被调用,"); System.out.println("非享元信息是:" + outState.getInfo()); }}
定义共享元工厂:
package com.siyi.flyweightpattern;import java.util.HashMap;import java.util.Map;//享元工厂角色public class FlyweightFactory { private Mapflyweights = new HashMap (); public Flyweight getFlyweight(String key) { Flyweight flyweight = flyweights.get(key); if (flyweight != null) { System.out.println("具体享元" + key + "已经存在,被成功获取!"); } else { flyweight = new ConcreteFlyweight(key); flyweights.put(key, flyweight); } return flyweight; }}
Main方法:
package com.siyi.flyweightpattern;public class Main { public static void main(String[] args) { FlyweightFactory factory = new FlyweightFactory(); Flyweight f01 = factory.getFlyweight("a"); Flyweight f02 = factory.getFlyweight("a"); Flyweight f03 = factory.getFlyweight("a"); Flyweight f11 = factory.getFlyweight("b"); Flyweight f12 = factory.getFlyweight("b"); f01.operation(new UnsharedConcreteFlyweight("第1次调用a。")); f02.operation(new UnsharedConcreteFlyweight("第2次调用a。")); }}
运行结果:
具体享元:a被创建!具体享元a已经存在,被成功获取!具体享元a已经存在,被成功获取!具体享元:b被创建!具体享元b已经存在,被成功获取!具体享元a被调用,非享元信息是:第1次调用a。具体享元a被调用,非享元信息是:第2次调用a。
优点:大大减少对象的创建,降低系统的内存,使效率提高。
缺点:提高了系统的复杂度,需要分离出外部状态和内部状态,而且外部状态具有固有化的性质,不应该随着内部状态的变化而变化,否则会造成系统的混乱。
使用场景: 1、系统有大量相似对象。 2、需要缓冲池的场景。
注意事项: 1、注意划分外部状态和内部状态,否则可能会引起线程安全问题。 2、这些类必须有一个工厂对象加以控制。
转载地址:http://lryof.baihongyu.com/