享元模式:是池技术的重要实现方式,使用共享对象可有效地支持大量的细粒度的对象,可以避免大量非常相似的类的开销;
案例:公司某部门给员工评优秀员工-很贴合实际哈;
抽象享元角色: /** * 抽象享元角色 */ public abstract class A1_Flyweight { //内部状态 部门 private String department="公司总部"; //外部状态 员工姓名 【定义成 final 类型的可以先思考下为什么】 private final String employeeName; //要求享元角色必须接受外部状态 public A1_Flyweight(String employeeName){ this.employeeName = employeeName; } //内部状态的 getter/setter public String getDepartment() { return department; } public void setDepartment(String department) { this.department = department; } //定义业务操作 public abstract void operate(); public String getEmployeeName() { return employeeName; } } 具体的享元角色: /** * 具体的享元角色 */ public class A2_FlyweightRole extends A1_Flyweight { public A2_FlyweightRole(String employeeName){ super(employeeName); } @Override public void operate() { System.out.println(this.getDepartment() +"-"+ this.getEmployeeName() +":优秀员工"); } } 享元工厂: /** * 享元工厂 */ public class A3_FlyweightFactory { //定义一个池容器 private static Map<String,A1_Flyweight> poll = new HashMap<String,A1_Flyweight>(); //享元工厂 public static A1_Flyweight getFlyweight(String employeeName){ A1_Flyweight result = poll.get(employeeName); if(null!=result){ return result; } //根据外部状态创建享元对象 result = new A2_FlyweightRole(employeeName); //放置到池中 poll.put(employeeName,result); return result; } /** * 获取 池容器 中对象数量 */ public static int getSize(){ return poll.size(); } }客户端调用:
/** * 客户端调用 */ public class A4_Client { public static void main(String[] args) { A3_FlyweightFactory factory = new A3_FlyweightFactory(); A2_FlyweightRole role1 = (A2_FlyweightRole)factory.getFlyweight("张三"); A2_FlyweightRole role2 = (A2_FlyweightRole)factory.getFlyweight("张三"); A2_FlyweightRole role3 = (A2_FlyweightRole)factory.getFlyweight("李四"); role1.operate(); role2.operate(); role3.operate(); int size = factory.getSize(); System.out.println("size:"+size); } }客户端调用结果:
公司总部-张三:优秀员工 公司总部-张三:优秀员工 公司总部-李四:优秀员工 size:2接收外部状态实现自己的业务逻辑,以便内部业务逻辑对外部状态的依赖。 注意,我们在 抽象享元 中对外部状态加上了 final关键字 ,是为了防止--获得了一个外部状态--然后无意修改了一下--池就混乱了!
享元模式分为:内部状态(intrinsic)与外部状态(extrinsic);
内部状态内部状态是对象可共享出来的信息,存储在享元对象内部并且不会随环境改变而改变,如我们例子中的department,它们 可以作为一个对象的动态附加信息,不必直接储存在具体某个对象中,属于可以共享的部分。
外部状态外部状态是对象得以依赖的一个标记,是随环境改变而改变的、不可以共享的状态,是唯一的一个索引值,如案例中的 employeeName;
当然实际工作中享元模式往往会跟其他设计模式协同使用,用的时候按照具体的场景灵活选择即可;
Integer类就是典型的享元模式的例子
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }Integer.valueOf中有一个IntegerCache,上面的代码中就对传入的值进行判断。
如果是从IntegerCache中取出就直接返回,否则就new一个Integer对象。
这也就是如果传入的int值不在固定的范围类,它们做==的时候一定是false,因为不是同一个对象。其中low=-128,high=127.
还有Long类的valueOf,也是同上的道理。