享元模式也是比较简单的,享元模式的定义为:使用共享对象可有效地支持大量的细粒度的对象。
说的白一点,就是把需要生成大量实例的对象内部结构细分,把能共享的数据抽象出来,形成一个新的对象,新对象的实例可以存在内存中供原有对象共享使用,从而减少内存的消耗。
享元模式的代码如下:
/** * Flyweight: 抽象出来的享元类 * * @author xuejupo [email protected] create in 2015-12-31 上午10:08:05 * */ abstract class Flyweight { // 不共享的状态 private String intrinsic; // 可以共享的状态 protected final String Extrinsic; // 要求享元角色必须接受外部状态 public Flyweight(String _Extrinsic) { this.Extrinsic = _Extrinsic; } // 定义业务操作 public abstract void operate(); // 内部状态的getter/setter public String getIntrinsic() { return intrinsic; } public void setIntrinsic(String intrinsic) { this.intrinsic = intrinsic; } } /** * ConFlyWeight: 具体的享元类 * * @author xuejupo [email protected] create in 2015-12-31 上午10:07:59 * */ class ConFlyWeight extends Flyweight { public ConFlyWeight(String _Extrinsic) { super(_Extrinsic); } @Override public void operate() { // TODO Auto-generated method stub System.out.println("我的业务逻辑处理"); } } /** * FlyweightFactory:享元对象工厂类--主要的逻辑 * * @author xuejupo [email protected] create in 2015-12-31 上午10:32:35 * */ class FlyweightFactory { // 定义一个池容器 private static HashMap<String, Flyweight> pool = new HashMap<String, Flyweight>(); // 享元工厂 public static Flyweight getFlyweight(String Extrinsic) { // 需要返回的对象 Flyweight flyweight = null; // 在池中没有该对象 if (pool.containsKey(Extrinsic)) { flyweight = pool.get(Extrinsic); } else { // 根据外部状态创建享元对象 flyweight = new ConFlyWeight(Extrinsic); // 放置到池中 pool.put(Extrinsic, flyweight); } return flyweight; } }
上面代码不太容易理解,下面代码用学生类来解释一下享元模式:
首先是不用享元模式的学生类:
package InvolvedMode.flyWeight; /** * Student : 学生类 * * @author xuejupo [email protected] create in 2015-12-31 上午10:47:25 */ public class Student { public Student(){} public Student(String name,int age,String academy, String president, String presidentSex, String academyInfo){ this.name = name; this.age = age; this.academy = academy; this.president = president; this.presidentSex = presidentSex; this.academyInfo = academyInfo; } private String name; private int age; // 所在学院president private String academy; // 院长 private String president; // 院长性别 private String presidentSex; // 学院其他信息 private String academyInfo; public String getName() { return name; } public int getAge() { return age; } public String getAcademy() { return academy; } public String getPresident() { return president; } public String getPresidentSex() { return presidentSex; } public String getAcademyInfoInfo() { return academyInfo; } }
学生工厂很简单,就不写了。。
在这个学生类里面,有院长和学院的相关信息,这些信息其实很多学生是相同的。
比如说需要实例化10000个计算机学院的学生,那么在这个10000个学生实例中,80%的信息都是重复的,这就造成了大量的内存浪费,而且如果院长换了,还要修改1万个学生实例,太麻烦,这种情况下我们就可以使用享元模式来做了,把学院信息提取出来:
package InvolvedMode.flyWeight; /** * StudentFlyWeight : 使用了享元的学生类 * @author xuejupo [email protected] * create in 2015-12-31 上午11:12:14 */ public class StudentFlyWeight extends Student{ public StudentFlyWeight(String name,int age,Academy academy){ this.name = name; this.age = age; this.academy = academy; } private String name; private int age; //学院bean private Academy academy; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getAcademy() { return academy.getAcademy(); } public String getPresident() { return academy.getPresident(); } public String getPresidentSex() { return academy.getPresidentSex(); } public String getAcademyInfoInfo() { return academy.getAcademyInfo(); } }
把学院信息抽象出来形成一个新类:
package InvolvedMode.flyWeight; /** * Academy : 学院类 * * @author xuejupo [email protected] create in 2015-12-31 上午10:51:04 */ public class Academy { public Academy(String academy, String president, String presidentSex, String academyInfo) { this.academy = academy; this.president = president; this.presidentSex = presidentSex; this.academyInfo = academyInfo; } // 学院名字 private String academy; // 院长 private String president; // 院长性别 private String presidentSex; // 学院其他信息 private String academyInfo; public final String getAcademy() { return academy; } public final void setAcademy(String academy) { this.academy = academy; } public final String getPresident() { return president; } public final void setPresident(String president) { this.president = president; } public final String getPresidentSex() { return presidentSex; } public final void setPresidentSex(String presidentSex) { this.presidentSex = presidentSex; } public final String getAcademyInfo() { return academyInfo; } public final void setAcademyInfo(String academyInfo) { this.academyInfo = academyInfo; } }
学生工厂类:
/** * StudentFactory: 学生工厂 * * @author xuejupo [email protected] create in 2015-12-31 上午11:24:11 * */ class StudentFactory { // 定义一个池容器 private static HashMap<String, Academy> pool = new HashMap<String, Academy>(); // 工厂方法,创建一个学生对象 public static StudentFlyWeight getStudent(String name, int age, Academy academy) { return new StudentFlyWeight(name, age, academy); } // 工厂方法,创建一个学生对象 public static StudentFlyWeight getStudentInstance(String name,int age,String academyName, String president, String presidentSex, String academyInfo ) { Academy academy = null; if(pool.containsKey(academyName)){ academy = pool.get(academyName); }else{ academy = new Academy(academyName, president, presidentSex, academyInfo); //把学院对象实例放到池子里 pool.put(academyName, academy); } return new StudentFlyWeight(academyName, age, academy); }
这样的话,如果计算机学院需要实例化1万个学生,那么学院类只需要实例化一个就够了。
享元模式很容易理解,就是把重复使用的资源共享呗,其实很多地方都能看到享元模式的影子。 接触最多的就是java的继承机制,一般我们会把所有子类公共的方法抽象出来,放到抽象的父类里面,这样所有的子类都能够使用继承自父类的方法了,这里就是享元模式的思想。
再比如,数据库相信很多人都用过,上面的学生类如果是一张学生表,那么相信有点数据库常识的人都会把他分成两张表,一张学生表一张学院表,然后两张表通过外键想通,这其实就是享元模式。个人觉得,享元模式更能体现出设计模式是一种思想而不是特定代码的这种感觉。