定义:使用共享对象可有效地支持大量的细拉度的对象。
类型:结构型模式
类图:
门面模式结构:
l 抽象享元角色(Flyweight):此角色是所有的具体享元类的超类,为这些类规定出需要实现的公共接口或抽象类。那些需要外部状态(External State)的操作可以通过方法的参数传入。抽象享元的接口使得享元变得可能,但是并不强制子类实行共享,因此并非所有的享元对象都是可以共享的。
l 具体享元(ConcreteFlyweight)角色:实现抽象享元角色所规定的接口。如果有内部状态的话,必须负责为内部状态提供存储空间。享元对象的内部状态必须与对象所处的周围环境无关,从而使得享元对象可以在系统内共享。有时候具体享元角色又叫做单纯具体享元角色,因为复合享元角色是由单纯具体享元角色通过复合而成的。
l 复合享元(UnsharableFlyweight)角色:复合享元角色所代表的对象是不可以共享的,但是一个复合享元对象可以分解成为多个本身是单纯享元对象的组合。复合享元角色又称作不可共享的享元对象。这个角色一般很少使用。
l 享元工厂(FlyweightFactoiy)角色:本角色负责创建和管理享元角色。本角色必须保证享元对象可以被系统适当地共享。当一个客户端对象请求一个享元对象的时候,享元工厂角色需要检查系统中是否已经有一个符合要求的享元对象,如果已经有了,享元工厂角色就应当提供这个已有的享元对象;如果系统中没有一个适当的享元对象的话,享元工厂角色就应当创建一个新的合适的享元对象。
l 客户端(Client)角色:本角色还需要自行存储所有享元对象的外部状态。
内部状态与外部状态:在享元对象内部并且不会随着环境改变而改变的共享部分,可以称之为享元对象的内部状态,反之随着环境改变而改变的,不可共享的状态称之为外部状态。
通用代码实现:
// 接口 interface FlyWeight { public void operation(String s); }
// 具体实现类 class ConcreteFlyWeight implements FlyWeight { private String str;// 内蕴状态 public ConcreteFlyWeight(String str) { this.str = str; } public void operation(String s) { System.out.println("内蕴变量:" + str); System.out.println("外蕴变量:" + s); } }
// 享元工厂 class FlyWeightFactory { public FlyWeightFactory() { } private Hashtable<String, ConcreteFlyWeight> flyWeights = new Hashtable<String, ConcreteFlyWeight>(); public ConcreteFlyWeight factory(String str) { ConcreteFlyWeight flyWeight; flyWeight = flyWeights.get(str); if (null == flyWeight) { flyWeight = new ConcreteFlyWeight(str); flyWeights.put(str, flyWeight); } return flyWeight; } public int getFlyWeightSize() { return flyWeights.size(); } }
public class Client { public static void main(String[] args){ FlyWeightFactory factory = new FlyWeightFactory(); FlyWeight flyWeight = factory.factory("a"); FlyWeight flyWeight2 = factory.factory("b"); FlyWeight flyWeight3 = factory.factory("a"); flyWeight.operation("a fly weight"); flyWeight2.operation("b fly weight"); flyWeight3.operation("c fly weight"); System.out.println(flyWeight == flyWeight3); System.out.println(factory.getFlyWeightSize()); } }运行结果
内蕴变量:a 外蕴变量:a fly weight 内蕴变量:b 外蕴变量:b fly weight 内蕴变量:a 外蕴变量:c fly weight true 2
门面模式的优点和缺点:
享元模式是一个非常简单的模式,它可以大大减少应用程序创建的对象,降低程序内存的占用,增强程序的性能,但它同时也提高了系统复杂性,需要分离出外部状态和内部状态,而且外部状态具有固化特性,不应该随内部状态改变而改变,否则导致系统的逻辑混乱.
门面模式的适用场景:
l 系统中存在大量的相似对象.
l 细粒度的对象都具备较接近的外部状态,而且内部状态与环境无关,也就是说对象没有特定身份。
l 需要缓冲地的场景。