面向对象很好地解决了系统抽象性的问题,同时在大多数情况下,也不会损及系统的性能。但是,在某些特殊的应用中下,由于对象的数量太大,采用面向对象会给系统带来难以承受的内存开销。比如图形应用中的图元等对象、字处理应用中的字符对象等。
采用纯粹对象方案的问题在于大量细粒度的对象会很快充斥在系统中,从而带来很高的运行时代价——主要指内存需求方面的代价。如何在避免大量细粒度对象问题的同时,让外部客户程序仍然能够透明地使用面向对象的方式来进行操作?
运用共享技术有效地支持大量细粒度的对象。
一,结构:
抽象享元(Flyweight)角色: 此角色是所有的具体享元类的超类,为这些类规定出需要实现的公共接口。那些需要外蕴状态(External State)的操作可以通过调用商业方法以参数形式传入。
具体享元(ConcreteFlyweight)角色: 实现抽象享元角色所规定的接口。如果有内蕴状态的话,必须负责为内蕴状态提供存储空间。享元对象的内蕴状态必须与对象所处的周围环境无关,从而使得享元对象可以在系统内共享的。
享元工厂(FlyweightFactory)角色: 本角色负责创建和管理享元角色。本角色必须保证享元对象可以被系统适当地共享。当一个客户端对象调用一个享元对象的时候,享元工厂角色会检查系统中是否已经有一个复合要求的享元对象。如果已经有了,享元工厂角色就应当提供这个已有的享元对象;如果系统中没有一个适当的享元对象的话,享元工厂角色就应当创建一个合适的享元对象。
客户端(Client)角色: 本角色需要维护一个对所有享元对象的引用。本角色需要自行存储所有享元对象的外蕴状态。
二,示例代码:
import java.util.Hashtable; /** * 享元工厂(FlyweightFactory)角色 * @author Salmon * */ public class FlyweightFactory { private Hashtable flyweights = new Hashtable(); public FlyweightFactory() { flyweights.put("X", new ConcreteFlyweight()); flyweights.put("Y", new ConcreteFlyweight()); flyweights.put("Z", new ConcreteFlyweight()); } public Flyweight getFlyweight(String key) { return ((Flyweight) flyweights.get(key)); } } /** * 抽象享元(Flyweight)角色 * @author Salmon * */ public interface Flyweight { public void operation(); } /** * 具体享元(ConcreteFlyweight)角色 * @author Salmon * */ public class ConcreteFlyweight implements Flyweight { public void operation() { System.out.println("ok"); } } /** * 客户端(Client)角色 * @author Salmon * */ public class Client { public static void main(String[] args) { FlyweightFactory f = new FlyweightFactory(); Flyweight fx = f.getFlyweight("X"); fx.operation(); Flyweight fy = f.getFlyweight("Y"); fy.operation(); Flyweight fz = f.getFlyweight("Z"); fz.operation(); } }