16_享元模式
【享元模式】
享元模式是池技术的重要实现方式。
享元模式使用共享对象有效地支持大量细粒度的对象。
享元模式两个要求:细粒度对象和共享对象。在平时写java程序过程中,分配太多的对象到应用程序中将有损程序的心梗,同事还容易造成内存溢出,避免的方式之一就是采用享元模式的共享技术。
要求细粒度对象,那么不可避免的使得对象数量多,且性质相近,我们将这些对象信息分为两部分:内部状态(intrinsic)和 外部状态(exetrinsic)。
* 内部状态
内部状态是对象可共享出来的信息,存储在享元对象内部并且不会随环境改变而改变。它可以作为一个对象的动态附加信息,不必直接存储在摸个具体的对象中,属于共享的部分。
* 外部状态
外部状态时对象得以依赖的一个标记,是随着环境改变而改变的、不可共享的状态。它是一批对象的统一标识,是唯一的一个索引值,相当于Map的键值key。
[ 目的 ]
享元模式的目的在于使用共享技术,使得一些细粒度的对象可以共享,我们的设计应该多使用细粒度的对象,这样便于重用或重构。
【分类】
[ 单纯享元模式 ]
在单纯享元模式中,所有享元对象都是可以共享的。
由3部分组成:
* Flyweight 抽象享元角色
简单的说就是一个产品的抽象类或接口,以规定出所有具体享元角色需要实现的方法。
* ConcreteFlyweight 具体享元角色
具体的一个产品类,实现抽象享元角色定义的业务。
* FlyweightFactory 享元工厂
职责非常简单,即构造一个池容器,同时提供从池中获得对象的方法。当一个客户端调用一个享元对象的时候,享元工厂角色应该先从对象池中获取,有则直接;若对象池中没有,则新实例化一个,并在对象池中放入该新实例化的对象。
[ 复合享元模式 ]
复合享元模式是将一些单纯享元模式加以复合,形成复合享元对象。这样的复合享元对象本身无法共享,但是他们能分解成单纯享元对象,后者可以分享。
* Flyweight 抽象享元角色
简单的说就是一个产品的抽象类或接口,以规定出所有具体享元角色需要实现的方法。
* ConcreteFlyweight 具体享元角色
具体的一个产品类,实现抽象享元角色定义的业务。
* ConcreteCompositeFlyweight 复合享元角色(不可共享的享元对象unsharedConcreteFlyweight)
不存在外部状态或安全要求(如线程安全)不能够使用共享技术的对象,该对象一般不会出现在享元工厂中。也称为不可共享的享元对象。
* FlyweightFactory 享元工厂
职责非常简单,即构造一个池容器,同时提供从池中获得对象的方法。当一个客户端调用一个享元对象的时候,享元工厂角色应该先从对象池中获取,有则直接;若对象池中没有,则新实例化一个,并在对象池中放入该新实例化的对象。
【单纯享元模式 例子】
package com.Higgin.Flyweight; import java.util.HashMap; import java.util.Map; /** * 抽象享元角色 */ interface Flyweight{ public void opetation(); } /** * 具体享元角色 */ class ConcreteFlyweight implements Flyweight{ private String state=null; public ConcreteFlyweight(String state) { this.state=state; } @Override public void opetation() { System.out.println("do some operation!"); } } /** * 享元对象的工厂类 */ class FlyweightFactory{ //HashMap类型的对象池 private static Map<String,Flyweight> map=new HashMap<>(); /** * 得到一个Flyweight * 1.对象池中已有的,直接获取 * 2.对象池中没有的,实例化一个,然后放入对象池中 */ public static Flyweight getFlyweight(String state){ Flyweight flyweight=map.get(state); //对象池中若有直接获取 if(flyweight==null){ //为null,即对象池中没有 System.out.println(state+" 不存在,需要实例化一个放入池中..."); //提示作用 flyweight=new ConcreteFlyweight(state); map.put(state, flyweight); }else{ //仅作为提示作用 System.out.println(state+" 已存在,无需实例化,直接取出..."); //提示作用 } return flyweight; } //得到对象池中的对象数量 public static int getObjectNum(){ return map.size(); } } /** * 测试 单纯享元模式 */ public class TestFlyweight { public static void main(String[] args) { Flyweight f1=FlyweightFactory.getFlyweight("小明"); Flyweight f2=FlyweightFactory.getFlyweight("小明"); Flyweight f3=FlyweightFactory.getFlyweight("小梦"); Flyweight f4=FlyweightFactory.getFlyweight("小杰"); Flyweight f5=FlyweightFactory.getFlyweight("小新"); Flyweight f6=FlyweightFactory.getFlyweight("小琴"); Flyweight f7=FlyweightFactory.getFlyweight("小琴"); System.out.println(f1==f2); System.out.println(f5==f6); System.out.println(f6==f7); System.out.println("创建的对象数量:"+FlyweightFactory.getObjectNum()); } }
【运行结果】