亨元(Flyweight Pattern)模式【结构模式第三篇】
亨元(Flyweight Pattern)模式
1、亨元模式的用意
亨元模式是对象的结构模式。亨元模式以共享的方式高效地支持大量的细粒度对象。
亨元模式能做到共享的关键是区分内蕴状态和外蕴状态
一个内蕴状态是存储在亨元对象内部的,并且是不会随环境改变而有所不同的。因此,一个亨元可以具有内蕴状态并可以共享。
一个外蕴状态是随环境改变而改变的、不可以共享的状态。亨元对象的外蕴状态必须由客户端保存,并在亨元对象被创建之后,
在需要使用的时候再传入到亨元对象内部。
外蕴状态不可以影响亨元对象的内蕴状态的,它们是相互独立的。
2、亨元模式的种类
根据所涉及的亨元对象的北部表象,亨元模式可以分为单纯亨元模式和复合亨元模式两种形式。
3、亨元模式的实现:
1)单纯亨元模式涉及的角色
1-抽象亨元角色:此角色是所有的具体亨元类的超类,为这些规定出需要实现的公共接口,那些需要外蕴状态的操作
可以通过方法的参数传入。抽象亨元的接口使得亨元变得可能,但是并不强制子类实行共享,因此并非所有的亨元
对象都是可以共享的
2-具体亨元角色:实现抽象亨元角色所规定的接口。如果有内蕴状态的话,必须负责为内蕴状态提供存储空间。
亨元对象的内蕴状态必须与对象所处的周围环境无关,从而使得亨元对象可以在系统内共享。有时候具体亨元角色
又叫做单纯具体亨元角色,因为复合亨元角色是由单纯具体亨元角色通过复合而成的
3-复合亨元角色:复合亨元角色所代表的对象是不可以共享的,但是一个复合亨元对象可以分解成为多个本身是单纯亨元
对象的组合。复合亨元角色又称做不可共享的亨元对象。
4-亨元工厂角色:本角色负责创建和管理亨元角色。本角色必须保证亨元对象可以被系统适当地共享。
当一个客户端对象请求一个亨元对象的时候,亨元工厂角色需要检查系统中是否已经有一个符合要求的亨元对象,
如果已经有了,亨元工厂角色就应当提供这个已有的亨元对象;如果系统中没有一个适当的亨元对象的话,
亨元工厂角色就应当创建一个新的合适的亨元对象。
5-客户端角色:本角色还需要自行存储所有亨元对象的外蕴状态。
//抽象亨元角色public abstract class Flyweight{public abstract void operation(String state);}//具体亨元角色具体亨元角色的主要责任:1)实现了抽象亨元角色所声明的接口,也就是operation()方法。operation()方法 接收一个外蕴状态作为参量。2)为内蕴状态提供存储空间,在本实现中就是intrinsicState属性。亨元模式本身对内蕴状态的存储类型并无要求 这里的内蕴状态是Character类型,是为了给符合亨元的内蕴状态选做String类型提供方便。public class ConcreteFlyweight extends Flyweight{private Character intrinsicState = null;public ConcreteFlyweight(Character state){this.intrinsicState = state;}//外蕴状态作为参量传入到方法中public void operation(String state){System.out.print("\nInternal State = " + intrinsicState + "Extrinsic State = " + state);}}//具体复合亨元角色具体复合亨元角色的责任:1)复合亨元对象是由单纯的亨元对象通过复合而成,因此它提供了add()这样的聚集管理方法。 由于一个复合亨元对象具有不同的聚集元素,这些聚集元素在复合亨元对象被创建之后加入,这本身就意味着 亨元对象的状态是会改变的,因此复合亨元对象是不能共享的。2) 复合亨元角色实现了抽象亨元角色所规定的接口, 也就是operation()方法。这个方法有一个参量, 代表复合亨元对象的外蕴状态,。一个复合亨元对象的所有单纯亨元对象元素的外蕴状态都是与复合亨元对象的 外蕴状态相等的,而一个复合亨元对象所含有的单纯亨元对象的内蕴状态一般是不相等的,不然就没有使用价值了。import java.util.Map;import java.util.HashMap;import java.util.Iterator;public class ConcreteCompositeFlyweight extends Flyweight{private HashMap flies = new HashMap(10);private Flyweight flyweight;public ConcreteCompositeFlyweight(){}//增加一个新的单纯亨元对象到聚集中public void add(Character key, Flyweight fly){flies.put(key,fly);}//外蕴状态作为参量传入到方法中public void operation(String extrinsicState){Flyweight fly = null;for(Iterator it = flies.entrySet().iterator()); it.hasNext();){Map.Entry e = (Map.Entry)it.next();fly = (Flyweight)e.getValue();fly.operation(extrinsicState);}}}//亨元工厂角色import java.util.Map;import java.util.HashMap;import java.util.Iterator;public class FlyweightFactory{private HashMap flies = new HashMap();public FlyweightFactory(){}//复合亨元工厂方法,所需状态以参量形式传入,这个参量恰好可以使用String类型public Flyweight factory(String compositeState){ConcreteCompositeFlyweight compositeFly = new ConcreteCompositeFlyweight();int length = compositeState.length();Character state = null;for(int i = 0; i < length; i ++){state = new Character(compositeState.charAt(i));System.out.println("factory(" + state +")");compositeFly.add(state,this.factory(state));}return compositeFly;}//单纯亨元工厂方法public Flyweight factory(Character state){//检查具有此状态的亨元是否已经存在if(flies.containsKey(state)){//具有此状态的亨元已经存在,因此直接将它返回retun (Flyweight)flies.get(state);}else{//具有此状态的亨元不存在,因此创建新实例Flyweight fly = new ConcreteFlyweight(state);//将实例存储到聚集中flies.put(state,fly);//将实例返回return fly;}}public void checkFlyweight(){Flyweight fly;int i = 0;System.out.println("\n==========CheckFlyweight()==============");for(Iterator it = flies.entrySet().iterator(); it.hasNext();){Map.Entry e = (Map.Entry) it.next();System.out.println("Item" + (++i) + ";" + e.getKey());}System.out.println("\n==========CheckFlyweight()==============");}}
在单纯的共享模式中使用单例模式实现共享工厂角色 import java.util.Map; import java.util.HashMap; import java.util.Iterator; public class FlyweightFactorySingleton{ private HashMap flies = new HashMap(); private static FlyweightFactorySingleton myself = new FlyweightFactorySingleton(); private FlyweightFactorySingleton(){} public static FlyweightFactorySingleton getInstance(){ return myself; } //工厂方法,向外界提供含有指定内蕴状态的对象 public synchronized Flyweight factory(Character state){ //检查具有此状态的亨元是否已经存在 if(flies.containsKey(state)){ //具有此状态的亨元对象已经存在,因此直接返还此对象 return (Flyweight)flies.get(state); }else{ Flyweight fly = new ConcreteFlyweight(state); flies.put(state,fly); return fly } } //辅助方法,打印所有已经创建的亨元对象清单 public void checkFlyweight(){ Flyweight fly; int i = 0; System.out.println("\n===========checkFlyweight==============="); for(Iterator it = flies.entrySet().iterator(); it.hasNext();){ Map.Entry e = (Map.Entry)it.next(); System.out.println("Item" + (++i) + ":" + e.getKey()); } System.out.println("\n===========checkFlyweight==============="); } } //客户端代码 public class ClientSingleton{ private static FlyweightFactorySingleton factory; public static void main(String args[]){ factory = FlyweightFactorySingleton.getInstance(); Flyweight fly = factory.factory(new Character('a')); fly.operation("First Call"); fly = factory.factory(new Character('b')); fly.operation("Second call"); Flyweight fly = factory.factory(new Character('a')); fly.operation("Third Call"); factory.checkFlyweight(); } } //将一个共享工厂角色用单例模式实现 import java.util.Map; import java.util.HashMap; import java.util.Iterator; public class FlyweightFactorySingleton{ private static FlyweightFactorySingleton myself = new FlyweightFactorySingleton(); private HashMap flies = new HashMap(); private Flyweight inkFlyweight; private FlyweightFactorySingleton(){} public static FlyweightFactorySingleton getInstance(){ return new FlyweightFactorySingleton(); } public Flyweight factory(String complexState){ ConcreteCompositeFlyweight complexFly = new ConcreteCompositeFlyweight(); int length = complexState.length(); Character state = null; for(int i = 0; i < length; i ++){ state = new Character(complexState.charAt(i)); System.out.println("factory(" + state + ")"); complexFly.add(state,this.factory(state)); } return complexFly; } public synchronized Flyweight factory(Character state){ //检查具有此状态的亨元是否已经存在 if(flies.containsKey(state)){ return (Flyweight)flies.get(state); }else{ Flyweight fly = new ConcreteFlyweight(state); flies.put(state,fly); return fly; } } public void checkFlyweight(){ Flyweight fly; int i = 0; System.out.println("\n===========checkFlyweight==============="); for(Iterator it = flies.entrySet().iterator(); it.hasNext();){ Map.Entry e = (Map.Entry)it.next(); System.out.println("Item" + (++i) + ":" + e.getKey()); } System.out.println("\n===========checkFlyweight==============="); } } //一个应用亨元模式的咖啡摊例子 //抽象亨元角色,serve()它没有参量是因为没有外蕴状态 public abstract class Order{ //将咖啡卖客人 public abstract void serve(); //返还咖啡的名字 public abstract String getFlavor(); }//具体亨元角色public class Flavor extends Order{private String flavor;public Flavor(String flavor){this.flavor = flavor;}public String getFlavor(){return this.flavor;}//将咖啡卖给客人public void serve(){System.out.println(System.out.println("Serving flavor " + flavor);}}//工厂角色public class FlavorFactory{private Order[] flavors = new Flavor[10];private int ordersMade = 0;private int totalFlavors = 0;//工厂方法,根据所需的风味提供咖啡public Order getOrder(String flavorToGet){if(ordersMade > 0){for(int i = 0 ; i < ordersMade; i ++){if(flavorToGet.equals(flavors[i].getFlavor())){return flavors[i];}}}flavors[ordersMade] = new Flavor(flavorToGet);totalFlavors++;return flavors[ordersMade++];}//辅助方法,返还创建过的风味对象的个数public int getTotalFlavorsMade(){return totalFlavors;}}//客户端代码,代表咖啡摊侍者public class ClientFlavor{private static Order[] flavors = new Flavor[20];private static int ordersMade = 0;private static FlavorFactory flavorFactory;//提供一杯咖啡private static void takeOrders(String aFlavor){flavors[ordersMade++] = flavorFactory.getOrder(aFlavor);} public static void main(String args[]){flavorFactory = new FlavorFactory();takeOrders("Black Coffee");takeOrders("Capucino");takeOrders("Espresso");takeOrders("Espresso");takeOrders("Capucino");takeOrders("Capucino");takeOrders("Black Coffee");takeOrders("Espresso");takeOrders("Capucino");//将所创建的对象卖给客人for(int i = 0; i < ordersMade; i ++){flavors[i].serve();}System.out.println("\nTotal teaFlavor objects made: " + flavorFactor.getTotalFlavorsMade() );}}//如果这个例子再大点,可以增加一个外蕴状态,也就是说可以增加桌子号,建立一个桌子类,将桌子号作为参数传给serve(Table table).